Web Worker 不负责文件读取,而是专注切片后的 CPU 密集任务(如哈希计算、格式解析);主线程用 File.slice() 轻量分片并 transfer ArrayBuffer 零拷贝传入 Worker,Worker 用 SparkMD5 等库并行处理,边算边回传进度,支持中断与续传。

大文件切片读取交给 Web Worker 处理,核心是把耗时的文件操作(如分片、哈希计算、格式解析)从主线程移出,避免阻塞 UI。关键不在于“读取”本身,而在于“谁来执行切片逻辑、谁来算校验值、谁来组织数据结构”。
切片动作本身可由主线程发起,但密集计算必须进 Worker
File.slice() 是轻量操作,只生成 Blob 引用,不拷贝数据,所以切片创建可以放在主线程。但一旦要对每个切片做 MD5/SHA1 计算、解析二进制结构(比如 Excel 的 zip 内部流)、或逐字节校验,就必须进 Worker——这些是纯 CPU 密集型任务。
- 主线程只需拿到 File 对象,按 chunkSize 切出 Blob 数组,然后 transfer 进 Worker
- Worker 接收后,用 FileReader 或直接读 ArrayBuffer,配合 SparkMD5、SheetJS 等库处理
- 避免在 Worker 中调用 DOM API 或使用 localStorage 等主线程专属接口
用 Transferable Objects 零拷贝传数据
大文件切片后若用 postMessage 传 Blob 或 ArrayBuffer,默认会深拷贝,内存和时间开销巨大。必须用可转移对象(Transferable)机制,让数据所有权移交,实现零拷贝。
- 主线程发送时写:
worker.postMessage({ file: file, chunkSize: 1024 * 1024 }, [file.arrayBuffer()]) - 注意:File 对象本身不可 transfer,但它的
arrayBuffer()或切片后的Blob.arrayBuffer()可以 - Worker 收到后直接操作 ArrayBuffer,无需再调用 readAsArrayBuffer
Worker 内部分批处理并回传进度
不要等全部切片算完才发结果。尤其对超大文件(如 5GB),应边算边通知主线程,支持实时进度条和中断恢复。
- Worker 每完成 10 个切片的哈希,就
postMessage({ type: 'progress', index: i, hash: h }) - 主线程监听 message,更新 UI,并可随时调用
worker.terminate()中断 - 若需续传,Worker 可接收已上传的 hash 列表,跳过对应切片
Vue/React 项目中注意加载方式
现代构建工具(Webpack/Vite)不原生支持 new Worker('xxx.js') 直接引用模块。需显式配置 loader 或使用构造函数语法。
- Vite 项目推荐:
const worker = new Worker(new URL('./uploader.worker.js', import.meta.url), { type: 'module' }) - Webpack 项目需装
worker-loader,并把 Worker 文件后缀设为.worker.js - 避免在 Worker 里用
import动态导入未打包资源;第三方库(如 spark-md5)要用importScripts加载 CDN 或本地脚本


















