计算文件MD5值实现文件秒传

3,881 阅读2分钟

“我报名参加金石计划1期挑战——瓜分10万奖池,这是我的第1篇文章,点击查看活动详情

日常开发过程中,经常会遇到需要上传文件的问题,有时候文件会特别的大,这时候需要考虑文件秒传文件分片上传。 以此来实现高效上传,提升用户体验。本文主要介绍文件秒传。

文件秒传原理

文件秒传的原理是在前端上传文件之前,拿到文件,并计算文件的MD5值,请求接口将MD5传递给后端,后端查询数据库是否存在相同的MD5值,如果存在,则直接返回对应的文件ID, 如果不存在,则返回空。

前端在收到响应后,如果文件id存在,则直接停止上传,将上传结果置为成功(秒传成功)。如果不存在,则走后续分片上传的流程。

常用组件

秒传关键在于计算文件MD5值,前端计算文件MD5值的常用工具为 spark-md5 它能够非常快速的计算大文件的MD5值, 满足开发需求。

函数封装

考虑到代码公用性,将此特抽出一个公用方法。 如下: 详见代码及注释。

import SparkMD5 from 'spark-md5';

/**
 * 计算文件Md5
 * 将文件分片逐步计算最终合并得出整个文件md5, 提升计算速度
 * @param {*} file
 */
 
 export default function computeFileMD5(file) { 
   return new Promise((resolve, reject) => {
      let blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice;
      let chunkSize = 2097152;  // 按照一片 2MB 分片
      let chunks = Math.ceil(file.size / chunkSize); // 片数
      let currentChunk = 0;
      let spark = new SparkMD5.ArrayBuffer();
      let fileReader = new FileReader();
      
      fileReader.onload = function (e) {
        console.log('read chunk nr', currentChunk + 1, 'of', chunks);
        spark.append(e.target.result);
        currentChunk++;

        if (currentChunk < chunks) {
          loadNext();
        } else {
          console.log('finished loading');
          let md5 = spark.end(); //最终md5值
          spark.destroy(); //释放缓存
          resolve(md5);
        }
      };
      
      fileReader.onerror = function (e) {
        console.warn('oops, something went wrong.');
        reject(e);
      };
      
      function loadNext() {
        let start = currentChunk * chunkSize,
        let end = ((start + chunkSize) >= file.size) ? file.size : start + chunkSize;
        fileReader.readAsArrayBuffer(blobSlice.call(file, start, end));
      }

      loadNext();
      
   }) 
 }

函数的调用

函数调用一般在文件上传前置函数,注意异步

async fileAdd(file) {
  // 注意此处file, file || file.file
  let md5 = await computeFileMD5(file.file);
  console.log(md5);
  // 调用接口实现秒传逻辑
}

总结

本文介绍了文件秒传的原理以及实现思路,其中对关键步骤获取md5做出了详细说明,以及示例了对应函数的封装和调用。希望可以帮助给有相关需求的人一些思路。