HTML5FormData上传大文件_HTML5分片上传断点续传实现说明【介绍】

1次阅读

formdata传大文件需手动分片上传,用file.slice()切2–5mb/片,每片带chunkindex、totalchunks、uploadid,服务端须支持任意顺序接收、幂等写入、断点查询及校验合并。

HTML5FormData上传大文件_HTML5分片上传断点续传实现说明【介绍】

FormData 传大文件会卡死或失败,因为没分片

浏览器原生 FormData 不处理分片,直接塞进内存上传,超 100MB 就容易触发内存警告、请求超时或 Network Error。服务端也可能拒绝未分片的巨量 payload。

真正能落地的做法是:手动切片 + 每片单独发 FormData 请求,靠唯一 uploadId 关联同一文件。

  • File.prototype.slice()(非 ArrayBuffer.slice)切,兼容性好,返回新 Blob
  • 每片加字段:chunkIndextotalChunksuploadId(前端生成 crypto.randomUUID() 或时间戳+随机数)
  • 不要等所有片发完再合并——服务端应支持「任意顺序接收」,靠 uploadId + chunkIndex 写临时文件

断点续传必须依赖服务端校验,前端只管重试逻辑

前端无法知道某片是否真被服务端落盘成功,只看 http 状态码不保险(比如 nginx 缓存了 200 但后端写失败)。断点能力本质在服务端是否提供 /upload/status?uploadId=xxx 接口

  • 上传前先 GET /upload/status?uploadId=xxx,返回已上传的 chunkIndex 列表
  • 跳过已存在的片,只发缺失的;注意服务端需对每个 chunkIndex 做幂等写入(如先检查文件是否存在)
  • 别用 XMLHttpRequest.upload.onprogress 估算进度——它反映的是浏览器发出数据的速度,不是服务端接收完成时间

chrome/firefox 对单个 FormData 的 Blob 大小没硬限制,但 V8 内存会爆

FormData.append('file', file.slice(0, 5 * 1024 * 1024)) 这种操作本身不会报错,但若切片太大(比如 50MB/片),js 引擎在构造 FormData 时可能把整个 Blob 加载进内存,触发 Chrome 的 RangeError: Maximum call stack size exceeded 或直接崩溃。

立即学习前端免费学习笔记(深入)”;

  • 安全切片大小建议:2–5MB/片(实测 Firefox 对 10MB/片开始明显卡顿)
  • file.slice(start, end) 而不是读成 ArrayBuffer 再转 Blob,避免双份内存占用
  • 上传中保持对 File 对象的弱引用即可,不用 URL.createObjectURL()——那玩意不释放会吃内存

服务端没实现分片合并,前端再努力也没用

很多前端同学花半天写分片逻辑,结果发现服务端收完所有片就扔了,或者合并时顺序错乱、校验缺失,最终文件损坏。这是最常被忽略的协同点。

  • 确认服务端是否支持按 uploadId 扫描临时目录、按 chunkIndex 排序拼接、最后做 md5sha256 校验
  • 要求服务端返回明确错误:比如 {"code": 4001, "msg": "chunk 5 missing"},而不是笼统的 500
  • 前端重试最多 3 次,第 4 次该报错就报错,别无脑循环——可能是服务端根本没监听那个 uploadId

分片和断点续传不是前端单方面能闭环的事,服务端接口设计决定了 80% 的成败。别在没对齐 API 合约前写一切片工具函数。

text=ZqhQzanResources