使用javascript计算大文件的MD5哈希值

时间:2016-08-23 23:14:44

标签: javascript md5 filereader cryptojs

如何上传500mb文件并使用CryptoJS获取MD5哈希?

这是我的代码:

$('#upload-file').change(function(){
    var reader = new FileReader();
    reader.addEventListener('load',function () {
        var hash = CryptoJS.MD5(CryptoJS.enc.Latin1.parse(this.result));
        window.md5 = hash.toString(CryptoJS.enc.Hex);
    });

    reader.readAsBinaryString(this.files[0]);
});

如果文件低于200mb,则可以。任何更大的东西,this.result都是空的“”。

我试过了:

filereader api on big files

javascript FileReader - parsing long file in chunks

几乎让这个工作,但控制台抱怨.join(“”)

http://dojo4.com/blog/processing-huge-files-with-an-html5-file-input

2 个答案:

答案 0 :(得分:8)

CryptoJS有一个progressive api for hash digests。其余部分从alediaferia's answer稍作修改。



function process() {
  getMD5(
    document.getElementById("my-file-input").files[0],
    prog => console.log("Progress: " + prog)
  ).then(
    res => console.log(res),
    err => console.error(err)
  );
}

function readChunked(file, chunkCallback, endCallback) {
  var fileSize   = file.size;
  var chunkSize  = 4 * 1024 * 1024; // 4MB
  var offset     = 0;
  
  var reader = new FileReader();
  reader.onload = function() {
    if (reader.error) {
      endCallback(reader.error || {});
      return;
    }
    offset += reader.result.length;
    // callback for handling read chunk
    // TODO: handle errors
    chunkCallback(reader.result, offset, fileSize); 
    if (offset >= fileSize) {
      endCallback(null);
      return;
    }
    readNext();
  };

  reader.onerror = function(err) {
    endCallback(err || {});
  };

  function readNext() {
    var fileSlice = file.slice(offset, offset + chunkSize);
    reader.readAsBinaryString(fileSlice);
  }
  readNext();
}

function getMD5(blob, cbProgress) {
  return new Promise((resolve, reject) => {
    var md5 = CryptoJS.algo.MD5.create();
    readChunked(blob, (chunk, offs, total) => {
      md5.update(CryptoJS.enc.Latin1.parse(chunk));
      if (cbProgress) {
        cbProgress(offs / total);
      }
    }, err => {
      if (err) {
        reject(err);
      } else {
        // TODO: Handle errors
        var hash = md5.finalize();
        var hashHex = hash.toString(CryptoJS.enc.Hex);
        resolve(hashHex);
      }
    });
  });
}

<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/components/core.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/components/md5.js"></script>
<input id="my-file-input" type="file">
<button onclick="process()">Process</button>
&#13;
&#13;
&#13;

答案 1 :(得分:0)

您不需要立即阅读整个文件,只需一次性将其全部提供给CryptoJS例程。

您可以创建哈希对象,并在阅读时提供块,然后获得最终结果。

取自CryptoJS documentation

的样本
var sha256 = CryptoJS.algo.SHA256.create();
sha256.update("Message Part 1");
sha256.update("Message Part 2");
sha256.update("Message Part 3");
var hash = sha256.finalize();