我在測試用google的CryptoJS庫來計算文件的md5和sha1。chrome
最簡單的異步調用瀏覽器
var fr = new FileReader; fr.onload=function(event){ var _bytelength = fr.result.byteLength; var binary = CryptoJS.lib.WordArray.create(fr.result); var md5 = CryptoJS.MD5(binary).toString(); var sha1 = CryptoJS.SHA1(binary); var base64 = sha1.toString(CryptoJS.enc.Base64);; console.log(md5); document.getElementById("message").innerHTML = "file " + currentFile.name + " is read" + "<p>" + "md5 is " + md5 + "<p>" + "sha1 is " + base64; } fr.readAsArrayBuffer(_file);
這樣是沒有問題的。異步
可是當我計算上百兆的文件的時候,一次性的load文件,瀏覽器就會崩掉,下面是改進代碼,區別是slice文件後,讀取每個blob,計算每個blog的md5,sha1,當讀完全部blob後,就計算出結果來。測試
function readFile(_file) { currentFile = _file; var startByte, endByte; startByte = endByte = 0; var fileSize = _file.size; var md5_cal = CryptoJS.algo.MD5.create(); var sha1_cal = CryptoJS.algo.SHA1.create(); var blob; var cnt = 0;//rememeber the count of calling of readBlob var readBlob = function(_blob) { var fr = new FileReader; fr.onload=function(event){ var binary = CryptoJS.lib.WordArray.create(fr.result); md5_cal.update(binary); sha1_cal.update(binary); cnt = cnt - 1; }; /*fr.onloadend=function(event){ if(this.readyState == FileReader.DONE) { var binary = CryptoJS.lib.WordArray.create(fr.result); md5_cal.update(binary); sha1_cal.update(binary); } };*/ fr.readAsArrayBuffer(_blob); }; while(endByte != fileSize) { endByte = Math.min(startByte + 102400, fileSize); blob = _file.slice(startByte, endByte); readBlob(blob); startByte = endByte; cnt = cnt + 1; } function printResultIfReady() { if(cnt == 0) { var md5 = md5_cal.finalize().toString(); var sha1 = sha1_cal.finalize(); var base64 = sha1.toString(CryptoJS.enc.Base64); document.getElementById("message").innerHTML = "file " + currentFile.name + " is read" + "<p>" + "md5 is " + md5 + "<p>" + "sha1 is " + base64; } else{ setTimeout(printResultIfReady, 500); } } setTimeout(printResultIfReady,500); }
但因爲異步調用的前後完成的順序不同,致使各個瀏覽器的計算結果不一樣,chrome的正確,ie和firefox錯誤,但各自不一樣。this
因而我改進下,就是當前一個blob讀取調用完成後,才進行下一個blob的讀取,這樣就沒有問題了。google
function readFile(_file) { currentFile = _file; var startByte, endByte; startByte = endByte = 0; var fileSize = _file.size; var md5_cal = CryptoJS.algo.MD5.create(); var sha1_cal = CryptoJS.algo.SHA1.create(); var blob; var cnt = 0;//rememeber the count of calling of readBlob var _readFile = function() { endByte = Math.min(startByte + 102400, fileSize); blob = _file.slice(startByte, endByte); readBlob(blob); startByte = endByte; cnt = cnt + 1; } var readBlob = function(_blob) { var fr = new FileReader; fr.onload=function(event){ var binary = CryptoJS.lib.WordArray.create(fr.result); md5_cal.update(binary); sha1_cal.update(binary); cnt = cnt - 1; if(endByte != fileSize) { _readFile(); } else{ printResultIfReady(); } }; fr.readAsArrayBuffer(_blob); }; function printResultIfReady() { var md5 = md5_cal.finalize().toString(); var sha1 = sha1_cal.finalize(); var base64 = sha1.toString(CryptoJS.enc.Base64); document.getElementById("message").innerHTML = "file " + currentFile.name + " is read" + "<p>" + "md5 is " + md5 + "<p>" + "sha1 is " + base64; } if(endByte != fileSize) { _readFile(); } }
代碼很醜陋,不過能夠說明問題就好。firefox