js封装一个分片计算sha1的方法

171 阅读1分钟

前言

我们在文件上传或者文件查询的接口中,时常需要给服务端传递一个文件的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>