前言
我们在文件上传或者文件查询的接口中,时常需要给服务端传递一个文件的sha1值作为参数。
对于小文件,可以一次性对文件内容进行sha1运算得出结果,但是对于大文件,我们一次性对文件进行sha1计算会导致浏览器卡死,因此需要进行分片计算。
依赖包
yarn add js-sha1
// or
npm install js-sha1
分片计算
/**
* @param {Object} options - 参数
* @param {File} options.file - file对象。element-ui的upload组件change事件中的file,需要使用file.raw
* @param {number} [options.chunkSize=2*1024*1024] - 对文件进行分片,每片的大小,单位byte
* @param {function} [options.onProgress] - 处理进度回调,返回{loaded, total},可以用来显示进度
* @returns {string} - sha1值
*/
const calcSHA1 = ({ file, chunkSize, onProgress }) => {
return new Promise((resolve) => {
// 分片大小
const _chunkSize = chunkSize || 2 * 1024 * 1024;
// 创建一个FileReader实例
const reader = new FileReader();
// 创建一个空的hash
const hash = sha1.create();
// 当前读取的文件位置
let curSize = 0;
// 读取文件内容,并更新位置
const readBlob = () => {
const endSize = Math.min(curSize + _chunkSize, file.size);
const blob = file.slice(curSize, endSize);
reader.readAsArrayBuffer(blob);
curSize = endSize;
};
reader.onloadend = ({ target }) => {
// 更新hash
hash.update(target.result);
// 如果没有到文件结尾,读取下一片;
if (curSize < file.size) {
readBlob();
// 返回最终的sha1
} else {
resolve(hash.toString());
}
// 执行进度事件
onProgress({ loaded: curSize, total: file.size });
};
// 读取第一片
readBlob();
});
};
调用示例
<template>
<input type="file" @change="handleChange">
</template>
<script>
export default {
methods: {
async handleChange(e){
const file = e.target.files[0];
const sha1 = await calcSHA1({file});
}
}
}
</script>