前端计算文件 hash
需要计算 文件 hash 传给后端进行核验;
网上搜到了几种方案:
名称 | arrayBuffer支持 | 追加支持 | npm地址 |
---|---|---|---|
spark-md5 | 支持 | 是 | https://www.npmjs.com/package/spark-md5 |
crypto-js/sha256 | 否 | 支持crypto定义的wordArray类型 | 否 https://www.npmjs.com/package/crypto-js |
sha.js | 否 | 支持buffer | 对nodejs友好 |
js-sha256 | 是 | 是 | https://www.npmjs.com/package/js-sha256 |
sha3-js | 是 | 是 | https://www.npmjs.com/package/js-sha3 |
小文件
如果是小文件,直接采用 js-sha256 即可,使用方法如下:
import { sha256 } from 'js-sha256';
const getHash = (blob: Blob) =>
new Promise((resolve) => {
const file = new FileReader();
file.onload = (e: ProgressEvent<FileReader>) => {
resolve(sha256(e.target?.result));
};
file.readAsArrayBuffer(blob);
});
但是超过 1G 的大文件计算 hash 的话,把文件一次性读入内存,非常耗浏览器内存,当文件比较大时,容易导致浏览器崩溃,电脑可能会卡死,因此需要考虑到 分片 计算;
分片计算hash
spark-md5
在网上找到了 spark-md5 可以分片读取文件计算hash,最后 append 一下,代码如下:
document.getElementById('file').addEventListener('change', function () {
var blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice,
file = this.files[0],
chunkSize = 2097152, // Read in chunks of 2MB
chunks = Math.ceil(file.size / chunkSize),
currentChunk = 0,
spark = new SparkMD5.ArrayBuffer(),
fileReader = new FileReader();
fileReader.onload = function (e) {
console.log('read chunk nr', currentChunk 1, 'of', chunks);
spark.append(e.target.result); // Append array buffer
currentChunk ;
if (currentChunk < chunks) {
loadNext();
} else {
console.log('finished loading');
console.info('computed hash', spark.end()); // Compute hash
}
};
fileReader.onerror = function () {
console.warn('oops, something went wrong.');
};
function loadNext() {
var start = currentChunk * chunkSize,
end = ((start chunkSize) >= file.size) ? file.size : start chunkSize;
fileReader.readAsArrayBuffer(blobSlice.call(file, start, end));
}
loadNext();
});
但是计算出来的 hash 是不对的,网上搜了一下 说是 编码方式问题 云云,最后放弃治疗;
crypto-js
使用 crypto-js 最后发现 16G 文件计算出来大概需要 8min 左右时间,时间比较理想,电脑也没卡,试了几台 win 和 mac ,20G 以内的文件是没什么问题的。代码如下:
import CryptoJs from 'crypto-js';
import encHex from 'crypto-js/enc-hex';
// 计算hash
const hashFile = (file) => {
const { size = 0 } = file;
/**
* 使用指定的算法计算hash值
*/
const hashFileInternal = (alog) => {
// 指定块的大小,这里设置为 20MB,可以根据实际情况进行配置,超过 100MB 的分片可能会卡
const chunkSize = 20 * 1024 * 1024;
/**
* 更新文件块的hash值
*/
const hashBlob = (blob, index) => {
// 格式化 fileList
formatFile(file, fileType.uploading, index / size);
return new Promise((resolve) => {
const reader = new FileReader();
reader.onload = ({ target }) => {
const wordArray = CryptoJs.lib.WordArray.create(target.result);
// CryptoJS update的方式,增量更新计算结果
alog.update(wordArray);
resolve();
};
reader.readAsArrayBuffer(blob);
});
};
let promise = Promise.resolve();
// 使用promise来串联hash计算的顺序。
// 因为FileReader是在事件中处理文件内容的,必须要通过某种机制来保证update的顺序是文件正确的顺序
for (let index = 0; index < size; index = chunkSize) {
promise = promise.then(async () => {
return hashBlob(file.slice(index, index chunkSize), index);
});
}
// 使用promise返回最终的计算结果
return promise.then(() => encHex.stringify(alog.finalize()));
};
// 计算文件的sha256,MD5 计算:CryptoJs.algo.MD5.create()
return hashFileInternal(CryptoJs.algo.SHA256.create());
};
通过对文件进行切片和增量更新hash的方式对文件进行 hash 计算,可以避免浏览器out of memory错误
使用异步计算hash值,计算返回promise,在promise.then()中获取计算结果。
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanhgfijhg
系列文章
更多
同类精品
更多
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
excel下划线不显示怎么办
PHP中文网 06-23 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
怎样阻止微信小程序自动打开
PHP中文网 06-13 -
TikTok加速器哪个好免费的TK加速器推荐
TK小达人 10-01