切片上传需手动用javascript实现,不能依赖原生表单提交;必须通过file.slice()分块、动态构造formdata、携带fileid/chunkindex/totalchunks等元数据,并配合进度、重试、断点续传等状态管理。

切片上传不是给 <input type="file"> 加个属性就能开箱即用的——它必须绕过原生表单提交,用 JavaScript 手动读取、分块、逐片发请求。原生 input 只负责选文件,后续全靠你控制。
为什么不能直接 submit 表单做切片
原生表单提交是原子操作:整个文件打成一个 multipart/form-data 包发出去,中间无法暂停、分段或重试。切片上传依赖的是 File 对象的 slice() 方法 + FormData 动态构造 + 多次 fetch 或 XMLHttpRequest。一旦用了 <form enctype="multipart/form-data"></form> + submit,就彻底交出控制权,切片无从谈起。
常见错误现象:event.target.files[0].slice() 报错(实际是 File.slice() 已废弃,该用 File.prototype.slice(),但更推荐用 file.slice(start, end));或者上传后后端收不到分片标识,因为没在每次请求里带 chunkIndex、totalChunks、fileId 等元数据。
- 必须监听
change事件拿到File实例,而不是等表单提交 -
File是Blob的子类,支持.slice(start, end),单位是字节,不是数组索引 - 每片上传都要附带相同
fileId(如用crypto.randomUUID()生成),否则后端无法拼接 - 别把分片逻辑塞进
submit处理器里——先event.preventDefault(),再手动走切片流程
前端结构怎么组织分片逻辑
核心是把“选文件 → 分片 → 上传 → 合并”拆成可中断、可恢复、可并发的步骤。不建议写成巨型函数,容易卡 UI 且难调试。
推荐结构:
- 顶层容器存
file、fileId、chunkSize = 5 * 1024 * 1024(5MB 常用值) - 用
Math.ceil(file.size / chunkSize)算出totalChunks - 上传队列用
Promise.allSettled()控制并发数(比如同时最多 3 片),避免浏览器打爆连接 - 每片构造独立
FormData:formData.append('chunk', blob)、formData.append('chunkIndex', i)、formData.append('totalChunks', totalChunks)、formData.append('fileId', fileId) - 上传成功后记录已传索引(存在内存或
localStorage),断点续传才可靠
切片上传必须带哪些字段给后端
光传二进制数据不够,后端需要上下文才能还原文件。少一个关键字段,服务端就只能存碎片、无法合并。
每次分片请求的 FormData 至少含:
-
chunk:当前分片的Blob(注意不是File,slice()返回的是Blob) -
chunkIndex:从 0 开始或从 1 开始,前后端必须约定一致 -
totalChunks:总片数,用于判断是否收齐 -
fileId:客户端生成的唯一 ID,所有分片共用,后端靠它聚合 -
filename:原始文件名(非路径),用于最终合并时命名,file.name即可 -
fileHash(可选但强烈推荐):前端用SparkMD5或Web Crypto API预算整个文件 Hash,传首片带上,后端校验完整性
漏掉 fileId 或 chunkIndex,后端根本没法区分这是哪个文件的第几片——所有分片会混在一起,合并逻辑直接崩。
预览、进度、失败重试怎么嵌入结构
切片上传的 UX 不是锦上添花,而是刚需。用户拖着大文件等十分钟,没进度条、没重试按钮,基本等于放弃。
实操要点:
- 预览:对图片类文件,用
FileReader.readAsDataURL(file)提前加载缩略图,不要等上传完 - 进度:按片统计比按字节统计更稳——
uploadedChunks / totalChunks,避免因网络抖动导致进度跳变 - 失败重试:记录失败的
chunkIndex,点击重试时只重新发那片,别全量重传 - 取消上传:调用
AbortController中止所有未完成的fetch,清理内存引用 - 禁用重复触发:选完文件后立刻禁用
input,防止用户手抖再点一次,生成新fileId导致混乱
真正麻烦的不是切片本身,而是状态同步:UI 进度、内存中的已传列表、本地存储的断点记录、后端实际接收情况——四者稍有不一致,用户就会看到“已传 99% 却卡住”或“重试后变成 200%”。别省略任何一环的状态维护。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











