service worker 无法直接保活大文件上传,需主线程切片、sw调度+chrome.alarms唤醒、服务端协同断点续传。

Service Worker 本身不能直接保活大文件上传任务,它不是后台进程,而是一个事件驱动、按需唤醒、空闲即终止的脚本。在 Chrome Manifest V3 或现代浏览器中,它没有“持续运行”能力,更不支持长期持有文件句柄、监听 XMLHttpRequest 进度或接管 fetch 流式上传。所谓“后台保活上传”,实际是靠组合策略实现状态可恢复 + 任务可续传 + 用户感知可控。
上传任务不能交给 Service Worker 直接执行
Service Worker 无法访问 File、Blob 或 FormData(主线程创建的对象无法序列化传入),也不能使用 XMLHttpRequest(不支持 onprogress)或原生 fetch 的流式上传(fetch 上传体为一次性 body,不提供分块进度回调)。强行在 SW 中发起上传,会因以下原因失败:
- 主线程传入的 Blob 在 postMessage 时被自动释放,SW 收到的是空引用
- SW 中调用 fetch 上传大文件会触发 30 秒 fetchTimeout,直接被 Chrome 强制中断
- SW 无权访问 FileReader,无法切片读取本地文件
- SW 被闲置 30 秒后终止,上传中断且无法自动续传
正确做法:主线程切片 + 后台状态托管 + 断点续传
把上传拆成三部分协作:
- 主线程负责文件读取与切片:用 FileReader 或 Blob.slice() 分块,每块 ≤ 5MB;生成唯一 uploadId 和分片序号
- 主线程发起首请求并获取上传凭证:如预签名 URL、token 或分片上传 ID,存入 chrome.storage.local
- Service Worker 仅做状态同步与轻量调度:监听 chrome.alarms 或 chrome.runtime.sendMessage 触发下一片上传;用 chrome.storage 持久化已传分片列表;通过 chrome.runtime.connect 告知前台页面当前进度
关键保活机制:用 chrome.alarms 替代 setInterval
Service Worker 不支持 setInterval 长期轮询,但 chrome.alarms 可在空闲后唤醒 SW 执行一次任务(即使页面关闭):
- 每上传完一片,设置一个 1–3 秒后的 alarm(名称含 uploadId)
- 在 SW 的 chrome.alarms.onAlarm.addListener 中检查该 uploadId 是否还有未传分片
- 有则调用 fetch 上传下一片;无则清理 storage 并通知前台完成
- alarm 是系统级唤醒源,不受 SW 空闲超时影响(但单次执行仍受 5 分钟 executionTimeout 限制)
断点续传必须依赖服务端配合
前端无法单靠 SW “记住上传到哪”,必须和服务端约定协议:
- 每次上传分片时携带 uploadId + chunkIndex + totalChunks
- 服务端记录每个 uploadId 已收哪些 chunk,并返回已存在 chunk 列表
- 主线程或 SW 拉取该列表后,跳过已传分片,只重传缺失项
- 最后由服务端合并,返回最终文件 URL
不复杂但容易忽略:上传状态不能存在内存里,所有 uploadId、chunkIndex、token 必须写入 chrome.storage.local;每次 SW 唤醒都先读 storage 再决策,而不是依赖全局变量。











