2022年 11月
 123456
78910111213
14151617181920
21222324252627
282930  

近期发布

近期评论

    2022 年 11 月 26 日

    Neusofts

    科技改变生活,创新引领未来

    HTML5读取文件MD5码

    背景

    自从html5 file api出现以来,我们可以做的事情越来越多,越来越有趣了,之前介绍过 《HTML5实现断点续传》、《HTML5实现拖拽下载》等关于File API的一些实例,今天分享一下,如何用HTML5 file api读取文件的MD5码。 MD5码在文件的唯一性识别上有很重要的应用,业内常用MD5进行文件识别、文件秒传、文件安全性检查等。 废话不多说,直接说重点。

    实现

    首先监听文本框的变化,告诉浏览器,你就看着这个input 如果有变化你就立刻执行之后的东西。

    document.getElementById("file").addEventListener("change", function() {
        //...
    }

    读取文件很容易通过input的files对象就可以读取到用户所选择的文件

    file = document.getElementById("file").files[0]

    之后就是分割文件了,由于文件可能会很大,比如说10G,20G所以一次性把它交个内存来处理会显得很残忍。于是我们把文件以2M作为一个片段进行分割,算出总共需要分成多少片

    var chunkSize = 2097152;
    chunks = Math.ceil(file.size / chunkSize);

    接着分割文件

    //file的slice方法,注意它的兼容性,在不同浏览器的写法不同
    blobSlice = File.prototype.mozSlice || File.prototype.webkitSlice || File.prototype.slice
    
    //然后指定file和开始结束的片段,就可以得到切割的文件了。
    blobSlice.call(file, start, end)

    一切做好之后,就要去读取文件的具体信息了。 这里我们用了Javascript的 FileReader() 方法,这个方法可以去读取用户本地文件的详细内容。 他的用法如下

    var fileReader = new FileReader();
    
    //blobSlice.call(file, start, end)就是之前分割文件的方法。
    //这里只要维护好start和end,就能一片一片的把文件传给fileRader对象了
    fileReader.readAsBinaryString(blobSlice.call(file, start, end));
    
    //最终每一段文件处理完毕都会触发fileReader的onload事件
    fileReader.onload = function(e){
        //e.target.result 就是我们要的片段信息
        //这里缓存获取到的片段,当所有片段完毕之后就可以进行MD5的计算了。
    }

    好了,到这里万事俱备只欠东风了。 由于原生的Javascript没有直接计算MD5的方法,这里我们引用了一个比较好的spark-md5库来辅助我们进行MD5的计算。 比较好的一点是,spark-md5处理文件的话也可以按片来计算。

    spark = new SparkMD5();
    spark.appendBinary(filepice1);
    spark.appendBinary(filepice2);
    spark.appendBinary(filepice3);
    
    //....
    
    //所有的分片处理好之后调用下面的方法就能获取到文件的MD5了
    spark.end()

    至此整个过程都已经结束了。 简单的描述就是:利用input选择文件 -> 对文件进行分片 -> 用FileReader方法读取文件 -> 交由Spark-md5进行处理。

    代码

    DEMO传送门

    附上完成的代码:

    //注意此方法引用了SparkMD5库 library:https://github.com/satazor/SparkMD5
    //监听文本框变化
    document.getElementById("file").addEventListener("change", function() {
      //声明必要的变量
      var fileReader = new FileReader(),
        box = document.getElementById('box');
    
      //文件分割方法(注意兼容性)
      blobSlice = File.prototype.mozSlice || File.prototype.webkitSlice || File.prototype.slice,
        file = document.getElementById("file").files[0],
    
        //文件每块分割2M,计算分割详情
        chunkSize = 2097152,
        chunks = Math.ceil(file.size / chunkSize),
        currentChunk = 0,
    
        //创建md5对象(基于SparkMD5)
        spark = new SparkMD5();
    
      //每块文件读取完毕之后的处理
      fileReader.onload = function(e) {
        console.log("读取文件", currentChunk + 1, "/", chunks);
    
        //每块交由sparkMD5进行计算
        spark.appendBinary(e.target.result);
        currentChunk++;
    
        //如果文件处理完成计算MD5,如果还有分片继续处理
        if (currentChunk < chunks) {
          loadNext();
        } else {
          console.log("finished loading");
          box.innerText = 'MD5 hash:' + spark.end();
          console.info("计算的Hash", spark.end());
        }
      };
    
      //处理单片文件的上传 
      function loadNext() {
        var start = currentChunk * chunkSize,
          end = start + chunkSize > = file.size ? file.size : start + chunkSize;
    
        fileReader.readAsBinaryString(blobSlice.call(file, start, end));
      }
    
      loadNext();
    });
    
    

    DEMO传送门