原生 无法暂停上传,因浏览器仅控制到文件选中,提交后由网络栈接管;需用 blob.slice() 分片 + abortcontroller 中断当前请求,并通过服务端查询已传大小实现断点续传。

原生 <input type="file"> 无法实现暂停,必须用 Blob.slice() 手动切片 + AbortController 中断请求。
为什么不能直接给 form 或 input 加暂停按钮
浏览器对 <input type="file"> 的控制权只到「选中文件」为止;一旦触发提交(无论是 form.submit() 还是 FormData + fetch),整个上传过程就交由底层网络栈接管,前端无权中断或查询进度。所谓“暂停”,本质是停止后续分片上传,并保留已传偏移量。
用 AbortController 暂停正在上传的分片
每个分片上传都应使用独立的 fetch 请求,并绑定一个 AbortController 实例。点击暂停时调用 abort(),就能中止当前正在发送的请求:
const controller = new AbortController();- 在
fetch(url, { signal: controller.signal })中传入signal - 暂停时执行
controller.abort(),该请求会立即 reject 并抛出AbortError - 注意:已成功响应的分片不受影响,服务端仍保留其数据
暂停后如何继续上传
继续 ≠ 重发所有分片,而是从服务端返回的已接收字节数开始切下一片:
- 调用
GET /upload/{uploadId}查询当前已传大小(如{ uploaded: 12582912 }) - 用
file.slice(uploaded, uploaded + chunkSize)切出下一小块 - 用相同
uploadId向PUT /upload/{uploadId}发送新分片,Header 带Content-Range: bytes 12582912-13631487/20971520 - 不要复用旧的
AbortController,每次新请求都新建一个
容易忽略的关键点
暂停状态必须持久化到本地(如 localStorage 或 IndexedDB),否则刷新页面后无法恢复上传位置;uploadId 要和服务端严格一致,且需防重复生成——它本质是文件唯一标识(可用文件名+大小+最后修改时间的哈希生成),不是随机 UUID。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











