资讯专栏INFORMATION COLUMN

文件下载时前后台MD5校验

Object / 1124人阅读

摘要:背景在项目中发现,文件下载时有可能出现文件不完全导致的文件无法打开的情况,考虑在后台响应中加入文件,与前台取得文件后生成的值作一次校验,来判断文件是否正确下载。

背景

在项目中发现,文件下载时有可能出现文件不完全导致的文件无法打开的情况,考虑在后台响应中加入文件MD5,与前台取得文件后生成的MD5值作一次校验,来判断文件是否正确下载。

问题

此功能的难点是如何在response中加入MD5值。原文件下载接口中使用的是HttpServletResponse,然后在前台使用a标签的点击事件来实现,在开发过程中,首先想到的是在response的headers中加入MD5信息,然后在前台想办法取到,即

...
// response.setHeader("md5",md5sum(bytes));
...

private String md5sum(byte[] bytes){
    ...
}

在实际开发中发现,这个方法无法正常下载文件,所以应该通过其他途径来实现。(这种想法还是很天真的2333)

方案

之前的开发中有用到Blob对象,在前台中可以使用Blob对象来实现文件下载,即

...
var url = window.URL.createObjectURL(blob);
var a = document.createElement("a");
a.href = url;
a.download = filename;
a.click();
...

那么肯定可以在后台接口中加上文件的bytearray,再在JS中使用var blob = new Blob([bytearray]);来声明一个blob对象实现文件下载,那么也可以在返回的JSON中加入生成的MD5值了。

代码
后台
import org.apache.commons.io.IOUtils;
import java.util.HashMap;
import java.util.Map;
import java.io.*;
import java.security.MessageDigest;
...
    private final char HEX_DIGITS[] = {"0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"};
    ...
    @Override
    public Object downloadFile(String burketName, String fileName){
        try {
            InputStream is = ...;
            byte[] byteArray = IOUtils.toByteArray(is);
            String fileMD5 = md5sum(byteArray);
            Map map = new HashMap();
            map.put("file",byteArray);
            map.put("md5",fileMD5.toUpperCase());

            if(is!=null){
                is.close();
            }
            return map;
        }catch (Exception ex){
            ex.printStackTrace();
        }
        return "";
    }

    private String toHexString(byte[] b) {
        StringBuilder sb = new StringBuilder(b.length * 2);
        for (int i = 0; i < b.length; i++) {
            sb.append(HEX_DIGITS[(b[i] & 0xf0) >>> 4]);
            sb.append(HEX_DIGITS[b[i] & 0x0f]);
        }
        return sb.toString();
    }

    private String md5sum(byte[] byteArray) {
        InputStream is = new ByteArrayInputStream(byteArray);
        byte[] buffer = new byte[1024];
        int numRead = 0;
        MessageDigest md5;
        try{
            md5 = MessageDigest.getInstance("MD5");
            while((numRead=is.read(buffer)) > 0) {
                md5.update(buffer,0,numRead);
            }
            return toHexString(md5.digest());
        } catch (Exception e) {
            System.out.println("parse md5 error");
            return null;
        }
    }
...
前台
...
// 前台在生成MD5时使用了SparkMD5插件
fetch(url, {headers:headers).then(function (res) {
    return res.json();
}).then(function (blob) {
    var spark = new SparkMD5.ArrayBuffer();
    //这个是接口中返回的MD5
    var serverMD5=blob.md5;
    var byteBuffer=_base64ToArrayBuffer(blob.file);
    spark.append(byteBuffer);
    var clientMD5 = spark.end().toUpperCase();
    // 判断文件是否下载完全
    if(serverMD5 === clientMD5){
        var f = new Blob([byteBuffer]);
        var url = window.URL.createObjectURL(f);
        var a = document.createElement("a");
        a.href = url;
        a.download =filename;
        a.click();
        window.URL.revokeObjectURL(f);
    }
    else{
        console.log("文件下载时出错,请重新下载");
    }
});

function _base64ToArrayBuffer (base64) {
    var binary_string =  window.atob(base64);
    var len = binary_string.length;
    var bytes = new Uint8Array(len);
    for (var i=0;i
总结

以上就是在开发文件下载校验时的思路和代码分享,开发的关键就是在文件下载接口返回值中加入后台计算的文件MD5,主要就是通过后台接口中返回文件的bytearray和用作校验的MD5值,前台接收到接口返回后生成一个MD5来与接口返回的MD5作校验,再在前台中使用返回的bytearray,通过Blob来实现文件下载。

如果你还有更好的方案,欢迎给我留言,不胜感激。

传送门

Blob: Blob

SparkMD5: SparkMD5

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/77255.html

相关文章

  • 文件下载后台MD5校验

    摘要:背景在项目中发现,文件下载时有可能出现文件不完全导致的文件无法打开的情况,考虑在后台响应中加入文件,与前台取得文件后生成的值作一次校验,来判断文件是否正确下载。 背景 在项目中发现,文件下载时有可能出现文件不完全导致的文件无法打开的情况,考虑在后台响应中加入文件MD5,与前台取得文件后生成的MD5值作一次校验,来判断文件是否正确下载。 问题 此功能的难点是如何在response中加入M...

    mingde 评论0 收藏0
  • JSPatch 部署安全策略

    摘要:综上,对称加密安全性低,若要稍微提高点安全性,就会提升程序复杂度。对于它的缺点数据内容泄露,其实在传输过程中不泄露,保存在本地同样会泄露,若对此在意,可以对脚本文件再加一层简单的对称加密。 使用 JSPatch 有两个安全问题: 传输安全:JS 脚本可以调用任意 OC 方法,权限非常大,若被中间人攻击替换代码,会造成较大的危害。 执行安全:下发的 JS 脚本灵活度大,相当于一次小型更...

    qqlcbb 评论0 收藏0

发表评论

0条评论

Object

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<