题引
秒传是通过计算文件hash值来确定文件内容的唯一性,这里我们使用CryptoJS
CryptoJS
是谷歌开发的一个纯JavaScript的加密算法类库,可以非常方便的在前端进行其所支持的加解密操作。目前crypto-js已支持的算法有:MD5,SHA-1,SHA-256,AES,Rabbit,MARC4,HMAC,HMAC-MD5,HMAC-SHA1,HMAC-SHA256,PBKDF2。常用的加密方式有MD5,SHA-1,SHA-256
以一个60M的文件为测试样本,经过1000次的测试平均值,三种算法的表现为:
MD5算法运行1000次的平均时间为:226ms
SHA1算法运行1000次的平均时间为:308ms
SHA256算法运行1000次的平均时间为:473ms
安全性方面,显然SHA256(又称SHA2)的安全性最高,但是耗时要比其他两种多很多。MD5相对较容易碰撞,但几率微乎其微,基本可以忽略,我倾向于这里使用MD5
代码
异步计算hash
function checksumFile(file) {
//可以将算法定义成变量
let algoInstance = CryptoJS.algo[options.algo].create(),
counter = 0
return new Promise((resolve, reject) => {
file.arrayBuffer().then(buffer => {
let length = buffer.byteLength,
chunks = Math.ceil(buffer.byteLength / options.chunkSize)
for (let i = 0; i < chunks; i++) {
let begin = i * options.chunkSize,
end = (i + 1) * options.chunkSize
let data = buffer.slice(begin, end)
let wordBuffer = CryptoJS.lib.WordArray.create(data) //memory leak
algoInstance.update(wordBuffer)
counter += data.byteLength
self.postMessage({
type: "progress",
content: {
file: file,
percentage: (counter / length).toFixed(2)
}
})
}
let checksum = algoInstance.finalize().toString()
resolve(checksum)
}).catch(err => {
self.postMessage({
type: "error",
content: “****”
})
reject(err)
})
})
}
总结
有没有注意到我代码里使用了postMessage,这是因为读取文件,计算hash,文件切换页面会出现卡顿,UI阻塞,这里使用了webworker,下章的主题