背景

在项目中发现,文件下载时有可能出现文件不完全导致的文件无法打开的情况,考虑在后台响应中加入文件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'};...@Overridepublic 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();//这个是接口中返回的MD5var 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<len;i++) {bytes[i] = binary_string.charCodeAt(i);}return bytes.buffer;
}

总结

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

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

传送门

  • Blob: Blob
  • SparkMD5: SparkMD5

文件下载时前后台MD5校验相关推荐

  1. java自定义注解实现前后台参数校验

    其实是可以通过@Constraint来限定自定义注解的方法. @Constraint(validatedBy = xxxx.class) 下面是我做的 java自定义注解实现前后台参数校验 的代码示例 ...

  2. Python实现文件md5校验

    Linux下校验文件MD5值,最简单的方法就是执行md5sum命令 md5sum filename 原本打算用subprocess调用系统命令来获取md5值, [python] view plainc ...

  3. python tcp黏包和struct模块解决方法,大文件传输方法及MD5校验

    https://www.cnblogs.com/zaizai1573/p/10230973.html 一.TCP协议 粘包现象 和解决方案 黏包现象 让我们基于tcp先制作一个远程执行命令的程序(命令 ...

  4. rsync同步远程主机目录,并通过md5校验目录

    一 rsync ​  rsync全称remote sync,是一种更高效.可以本地或远程同步的命令,之所以高效是因为rsync会对需要同步的源和目的进度行对比,只同步有改变的部分,所以比scp命令更高 ...

  5. linux 目录md5校验,【我的Linux,我做主!】浅谈MD5校验文件完整一致性

    目录: (一)MD5介绍 (二)md5sum命令 (三)实战演练 (一)MD5介绍 (1.1)MD5即Message-Digest Algorithm 5(信息-摘要算法 第5版),用于确保信息传输完 ...

  6. 文件完整性校验之MD5校验

    文件完整性校验之MD5校验 在现代计算机系统中,文件安全和完整性保护是至关重要的.不仅是个人用户需要保护他们的数据免受恶意软件和黑客攻击,企业和机构也需要确保其敏感数据的完整性和机密性. MD5校验是 ...

  7. Windows系统下对文件进行MD5校验

    MD5全称MD5信息摘要算法(MD5 Message-Digest Algorithm),是一种被广泛使用的密码散列函数,用于确保信息传输完整一致. 如今,MD5虽然被证明安全性不足,但被广泛运用于文 ...

  8. 生成文件md5校验码可满足大于2G情况

    对于文件生成md5校验码,在实际开发中用处很大,有利于比较服务器上是否已经存在该文件,哪怕文件名不一致也无所谓. 由于存在超大文件,经过从网上查找,得到两种方法,一种是利用MappedByteBuff ...

  9. 脚本_根据 md5 校验码,检测文件是否被修改

    #!bin/bash #功能:根据 md5 校验码,检测文件是否被修改 #作者:liusingbon #本示例脚本检测的是/etc 目录下所有的 conf 结尾的文件,根据实际情况,您可以修改为其他目 ...

最新文章

  1. 嵌入式linux结构框图,嵌入式linux系统的结构
  2. 程序员到了35 岁就要被裁员?
  3. SQL SERVER 2008的元数据视图
  4. session 详解
  5. springcloud阿里巴巴五大组件_如何无缝迁移 SpringCloud/Dubbo 应用到 Serverless 架构
  6. html流星雨代码_HTML制作流星雨特效
  7. Rust 1.34.0 发布
  8. java便签小程序原码_localStorage实现便签小程序
  9. bfv同态加密_五分钟了解同态加密及三种常见方案
  10. thinkphp中的__DIR__ __ROOT__ __APP__ __MODULE__ APP_PATH LIB_PATH MODULE_PATH 等是在哪里定义的?...
  11. 影像测量仪使用的注意点
  12. lcx 通过端口转发实现内网穿透
  13. 2022Vue经典面试题及答案汇总(持续更新)
  14. 用opencv将左右眼3D图片转换为红蓝3D图片
  15. android edittext底线,Android定制自己的EditText轻松改变底线颜色
  16. centos7加载磁盘
  17. vue玩转移动端H5微信支付和支付宝支付
  18. Jquery 模糊匹配ID
  19. 2021年危险化学品经营单位安全管理人员考试题及危险化学品经营单位安全管理人员证考试
  20. 虹软人脸识别 - faceId及IR活体检测的介绍

热门文章

  1. 我的漫漫程序人生路(上)
  2. 点阵---点亮一个点(内含硬件设计+软件编程+思路)
  3. 学软件开发的理由_成为软件开发人员的8个理由
  4. php语言查找字符串是否存在,PHP语言查找字符串是否存在的方法
  5. 顺丰api相关示例 - java版本(带打印)
  6. android surfaceflinger 老罗,《老罗的Android之旅》阅读笔记——SurfaceFlinger服务
  7. 2018 趁热说几句区块链,它真的能改变一切吗?
  8. 服务器端渲染和客户端渲染有什么区别?
  9. 托爾斯泰《安娜‧卡列妮娜》的寫作背景
  10. c语言简单编程题目及答案,经典练习C语言编程的题目及答案整理.pdf