必须用 readablestream 而非 blob/text,因为 blob() 仍需内存解码,text() 直接生成巨型字符串易致堆溢出;只有 arraybuffer() 或 body.getreader() 提供原始字节流控制权,支持分块、跳过、截断等增量操作。

在 Web Worker 中基于 Fetch Stream 实现边下载边增量加工,核心在于避开“全量加载→内存处理”这一高危路径,转而用流式读取 + 分块解析 + 增量输出的方式,让大文件处理既不卡主线程,也不爆内存。
为什么必须用 ReadableStream 而非 blob/text
Worker 中调用 fetch 后,response.blob() 或 response.text() 仍是危险操作:
-
blob()会把整个响应体暂存为 Blob 对象,后续若需解析(如转 JSON、拆 CSV 行),仍得读入内存解码; -
text()更严重——直接触发 UTF-8 解码并生成巨型字符串,几 GB 文本极易导致 Worker 堆溢出; - 只有
response.arrayBuffer()或response.body.getReader()提供原始字节流控制权,适合分块、跳过、截断、对齐等增量操作。
关键步骤:流读取 → 分块加工 → 增量输出
以处理一个超大日志文件(GB 级、按行分割)为例:
- 用
fetch(url).then(res => res.body.getReader())获取流读取器; - 循环调用
reader.read()拿到Uint8Array分块; - 每块内按
\n或\r\n切行,但注意末尾不完整行需缓存到下一块拼接(避免跨行截断); - 对每一行做轻量加工(如过滤、提取字段、时间格式化),结果可立即写入 IndexedDB、或通过
postMessage推送至主线程渲染、或累积成新 Blob 分片供后续合并。
如何安全回传加工结果给主线程
Worker 与主线程通信需遵守结构化克隆规则,不能传 ArrayBuffer 以外的大对象:
- 加工后的文本行建议转为字符串数组(小批量),或压缩为 base64 片段再传递;
- 若需回传二进制数据(如加密后片段、摘要哈希),优先用
ArrayBuffer+transferables选项,避免拷贝开销; - 高频小数据可用
postMessage({type: 'chunk', data: [...]}),配合主线程的 requestIdleCallback 渲染,防 UI 卡顿。
补充:配合 Range 分片提升可控性
若后端支持 HTTP Range 请求,可在 Worker 中主动分片下载(如每片 10MB),再逐片流式加工:
- 首片从
bytes=0-10485759开始,读到最近换行符位置,记为实际结束点; - 下一片从该位置 +1 开始,确保每片都以完整行为边界;
- 各片独立加工、独立校验(如 CRC32)、独立上报进度,失败可重试单片而非整文件。











