使用webworker优化大文件生成hash的几种方式

最近做大文件断点续传需求时,需要将大文件生成hash,如果直接生成,速度会变得很慢。

优化方式:将大文件先切片,每一片都启动一个webWorker来计算hash,最后将所有的hash合并到一起再重新生成一个新的hash。

js 复制代码
    async function calculateMD5All(file: File) {
        const chunkSize = 100000000; // 100MB
        const chunks = Math.ceil(file.size / chunkSize);
        let currentChunk = 0;
        const promiseAll: Promise<unknown>[] = [];
        function loadNext() {
            const start = currentChunk * chunkSize;
            const end = Math.min(start + chunkSize, file.size);
            promiseAll.push(creatWebworker(file.slice(start, end)));
            currentChunk++;
            if (currentChunk < chunks) {
                loadNext();
            }
        }
        loadNext();
        const arr = await Promise.all(promiseAll);
        const hash = SparkMD5.hash(arr.join(','));
        return hash;
    }

方式1: 原生js引入

ini 复制代码
    // 引入worker.js,我是vite+vue3项目,worker.js放在项目的public目录下
    
    function creatWebworker(chunk: Blob) {
        // worker.js的地址可以用绝对地址也可以是相对地址,因为我直接放在public目录下,部署后就在项目根路径下
        const worker = new Worker('/worker.js'); 
        worker.onmessage = (e) => {
            const hash = e.data;
            resolve(hash);
        };
        worker.postMessage(chunk);
    }
    
    
    /**
    * worker.js
    */
    
    // spark-md5.min.js的地址我也是放在public项目下,所以这里可以写相对地址,注意:importScripts引入的js必须和当前项目的域名同源。
    importScripts('/spark-md5.min.js');

    self.onmessage = function (e) {
        const chunk = e.data;
        const spark = new SparkMD5.ArrayBuffer();
        const fileReader = new FileReader();
        fileReader.readAsArrayBuffer(chunk);
        fileReader.onload = function (e) {
            spark.append(e.target?.result);
            const hash = spark.end();
            self.postMessage(hash);
        };
    };

方式2:Blob URL引入

ini 复制代码
// 这种方式是使用使用Blob URL,其实只是将1中的worker.js变成了模板字符串。注意要注意一点,和1有点不同的是importScripts中的路径只能是通域名下的绝对路径
const workerCode = `
    importScripts('https://***/spark-md5.min.js');
    self.onmessage = function (e) {
        const chunk = e.data;
        const spark = new SparkMD5.ArrayBuffer();
        const fileReader = new FileReader();
        fileReader.readAsArrayBuffer(chunk);
        fileReader.onload = function (e) {
            spark.append(e.target?.result);
            const hash = spark.end();
            self.postMessage(hash);
        };
    };
`;
const blob = new Blob([workerCode], { type: 'application/javascript' });
const worker = new Worker(URL.createObjectURL(blob));
worker.onmessage = (e) => {
    const hash = e.data;
    resolve(hash);
};
worker.postMessage(chunk);

方式3:ESModule引入 (推荐这种)

ini 复制代码
// worker.ts文件直接写在主文件同级目录下,创建worker时,设置type:module
    function creatWebworker(chunk: Blob) {
        return new Promise((resolve, reject) => {
            const worker = new Worker(new URL('./worker.ts', import.meta.url), { type: 'module' });
            worker.onmessage = (e) => {
                const hash = e.data;
                resolve(hash);
            };
            worker.postMessage(chunk);
        });
    }
    
 // worker.ts

import SparkMD5 from 'spark-md5';
self.onmessage = function (e) {
    const chunk = e.data;
    const spark = new SparkMD5.ArrayBuffer();
    const fileReader = new FileReader();
    fileReader.readAsArrayBuffer(chunk);
    fileReader.onload = function (e) {
        spark.append(e.target?.result as ArrayBuffer);
        const hash = spark.end();
        self.postMessage(hash);
    };
};   
    
相关推荐
Mr Xu_2 分钟前
Vue 3 中 watch 的使用详解:监听响应式数据变化的利器
前端·javascript·vue.js
未来龙皇小蓝5 分钟前
RBAC前端架构-01:项目初始化
前端·架构
程序员agions14 分钟前
2026年,微前端终于“死“了
前端·状态模式
万岳科技系统开发14 分钟前
食堂采购系统源码库存扣减算法与并发控制实现详解
java·前端·数据库·算法
程序员猫哥_21 分钟前
HTML 生成网页工具推荐:从手写代码到 AI 自动生成网页的进化路径
前端·人工智能·html
龙飞0522 分钟前
Systemd -systemctl - journalctl 速查表:服务管理 + 日志排障
linux·运维·前端·chrome·systemctl·journalctl
我爱加班、、27 分钟前
Websocket能携带token过去后端吗
前端·后端·websocket
AAA阿giao27 分钟前
从零拆解一个 React + TypeScript 的 TodoList:模块化、数据流与工程实践
前端·react.js·ui·typescript·前端框架
杨超越luckly33 分钟前
HTML应用指南:利用GET请求获取中国500强企业名单,揭秘企业增长、分化与转型的新常态
前端·数据库·html·可视化·中国500强
hedley(●'◡'●)1 小时前
基于cesium和vue的大疆司空模仿程序
前端·javascript·vue.js·python·typescript·无人机