必须用fetch主动探测+abortcontroller设超时(如5000ms)判断真实断网,失败即abort上传并存fileid、uploadedchunks、currentchunkindex至localstorage(隐私模式降级内存);恢复后延迟3秒调checkandresume比对服务端状态再续传,每片限重试3次。

断网时不能让上传直接失败或卡死,必须立即暂停、暂存状态、等恢复后再续传——这需要主动探测网络 + 阻断默认行为 + 本地持久化三者配合,缺一不可。
如何用 fetch + AbortController 检测断网并挂起上传
浏览器的 navigator.onLine 不可靠,它只反映浏览器 UI 状态,真实断网时经常返回 true。必须在上传过程中主动探测:
- 每次发分片请求前,先用
fetch('/favicon.ico', { method: 'HEAD', cache: 'no-store' })发一个轻量探测(同源、无跨域风险) - 用
AbortController设定超时(如5000ms),超时即视为断网,触发挂起逻辑 - 不要在
catch里直接重试——fetch失败可能是 DNS、SSL 或服务端问题,需区分对待 - 探测失败后,立刻调用当前分片请求的
abort(),并保存当前chunkIndex和已成功上传的索引列表
挂起时 localStorage 存什么、怎么存才安全
挂起不是“记下进度条数字”,而是存可恢复的最小执行单元。存错字段会导致重连后无法续传或重复提交:
- 必须存:
fileId(基于文件内容的 MD5,不能是name + size)、uploadedChunks(已确认写入磁盘的索引数组,如[0,1,2])、currentChunkIndex(正在上传但未确认的那片序号) - key 必须是
offline-upload-${fileId},避免多文件/多标签覆盖 - 必须包
try/catch:隐私模式下localStorage.setItem会直接抛SecurityError,降级存到内存对象pendingUploads = {} - 不要存原始 Blob 或 base64,只存元数据;文件内容留在
File对象引用中(它不序列化)
重新联网后怎么避免“自动狂发”导致失败
监听 window.addEventListener('online') 只是信号,不是执行指令。立刻发请求大概率失败:
- 用户可能刚切回页面,资源还没加载完;Chrome 在 Tab 非激活时会节流 fetch
- 应延迟执行:用
setTimeout(() => checkAndResume(), 3000),等页面稳定 -
checkAndResume()的核心是再发一次/upload/status?fileId=xxx,和服务端比对最新已传列表,而不是盲信 localStorage - 每片重试最多 3 次,失败后标记
status: 'failed'并停止自动重试,交由用户手动触发“重试全部”
真正难的不是挂起动作本身,而是挂起后的状态一致性——前端存的、服务端记的、用户感知的进度,三者必须始终对齐。任何一方掉队,续传就会变成“传一半丢一半”或者“传两遍毁一份”。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











