1、概述
    本文将阐述 为何需要计算文件的MD5值,为何需要在web-worker中计算,具体的实现方案与对比

2、为何需要计算文件的MD5值
    文件的MD5值是文件的哈希映射,可以简单理解为基于文件内容生成的唯一码,在文件上传中,可以通过在文件头写入MD5值在服务端和客户端之间进行约定,避免接收到的是损坏或者篡改的内容
3、为何需要在web worker中计算
    文件的MD5值计算是纯运算,将阻塞JS主线程的运行,在文件较大时,计算过程将使得浏览器长时间处于无响应状态
    而web-worker与JS处于不同的线程,相互并不阻塞,因此可以将一些耗时的纯运算放在web-worker中进行,等待完成后通知到JS主线程
    看一个简单的例子:
<input type="file" id="file"/>
<script src="https://cdn.bootcss.com/crypto-js/3.1.9-1/crypto-js.min.js"></script>
file.onchange = ((e)=>{
    var reader = new FileReader();
    reader.onload = function (e) {
        // CryptoJS.MD5 参数必须是 string 或者 ArrayBuffer
        console.log(CryptoJS.MD5(reader.result).toString())
    };
    reader.readAsText(e.target.files[0], "utf-8");
})
setInterval(() => { console.log(1) }, 1000)
     setInterval 的执行在计算过程中会被中断
4、web-worker 实现方案
    要点:
    (1) MD5 的计算不自己造轮子,采用 CryptoJS 提供的方法,需要注意的是 CryptoJS.MD5 接收的参数是 String 类型,因此需要使用 FileReader.readAsText 先将文件转成 String
    (2) Worker 不能读取本地文件,因此测试时需要启动一个http的本地服务
    (3) 主线程通过 worker.postMessage 向 Worker线程 发送文件内容,onmessage监听Worker线程返回的数据Worker线程使用 addEventListener 监听 message 事件,在收到数据并完成计算后使用 self.postMessage 返回给主线程,其中 self 的Worker线程的全局对象
    (4) 主线程引入的三方库不能共享给 Worker线程,因此需要在 Worker线程 中使用 importScripts 动态加载
    主线程代码,相较原始方案,此例把文件的解析和MD5的计算放到了Worker线程("./fileworker.js")中,并且删除了 CryptoJS 的CDN,因为用不到了
<input type="file" id="file"/>
var worker = new Worker("./fileworker.js")
worker.onmessage = function(e){
    console.log(e.data)	// 得到计算后的md5
}
file.onchange = ((e)=>{
    worker.postMessage(e.target.files[0])
})
setInterval(() => { console.log(1) }, 1000)
    fileworker.js 代码
// 动态加载依赖
self.importScripts("https://cdn.bootcss.com/crypto-js/3.1.9-1/crypto-js.min.js")

self.addEventListener("message", (e) => {
  readFile(e.data)
})

function readFile(file) {
  var reader = new FileReader();
  reader.onload = function (e) {
    // CryptoJS.MD5 参数必须是 string
    self.postMessage(CryptoJS.MD5(reader.result).toString())
  };
  reader.readAsText(file, "utf-8");
}
    计算过程中不会影响 setInterval 的执行
5、后续的实践
    上文实现的是一个基础的计算文件MD5的功能,但在工程化的项目中,需要考虑webpack的配置,尝试使用模块的方式注入三方库而不是依赖CDN等等,后续补充。