JavaScript分片上传时如何获取Blob的正确字节大小
分片上传异常的问题排查与修复方案
我帮你看了这段分片上传的代码,几个细节问题很可能就是导致分片异常的原因,咱们一步步捋:
问题1:FormData 没有每次循环重新创建
你现在的代码里,FormData应该是在循环外创建的吧?每次循环都往同一个FormData里append chunkFile,会导致每个请求都带着之前所有的分片数据,后端收到的文件自然是乱的。每次分片请求都要新建一个FormData实例。
问题2:File.slice 的参数逻辑错误
file.slice(start, end-1) 这里的问题很大:
- File.slice的第二个参数是结束位置(不包含该位置的字节),你写
end-1会让每个分片少一个字节,最后合并出来的文件会缺失内容 - 初始的end设置和更新逻辑也有问题,应该用
start + chunkSize作为结束位置,同时要处理最后一个分片不能超过文件总大小的情况
问题3:异步请求的顺序问题
循环里直接批量发送XHR请求,都是异步执行的,后端收到分片的顺序可能和你发送的顺序不一致,最后合并的时候就会把文件拼错。要么改成串行请求(上一个分片上传成功再发下一个),要么给每个分片带上索引标记,让后端能按正确顺序合并。
修正后的代码示例
const chunkSize = 1024 * 1024; // 假设按1MB分片 const fileSize = file.size; let start = 0; // 用串行方式上传,保证分片顺序正确 function uploadNextChunk() { if (start >= fileSize) return; const end = Math.min(start + chunkSize, fileSize); const blob = file.slice(start, end); const formData = new FormData(); // 每次请求新建FormData,避免数据叠加 // 给后端带上分片标识,方便合并 formData.append('chunkFile', blob, file.name); formData.append('chunkIndex', Math.floor(start / chunkSize)); formData.append('totalChunks', Math.ceil(fileSize / chunkSize)); const xhr = new XMLHttpRequest(); xhr.addEventListener('load', function (e) { console.log(`分片 ${Math.floor(start / chunkSize)} 上传完成`, e); start = end; uploadNextChunk(); // 触发下一个分片上传 }, false); xhr.addEventListener('error', function (e) { console.error(`分片 ${Math.floor(start / chunkSize)} 上传失败`, e); // 这里可以添加重试逻辑 }, false); xhr.open('POST', '../saveUrl'); xhr.send(formData); } // 启动分片上传 uploadNextChunk();
额外提示
- 后端一定要根据
chunkIndex和totalChunks来按顺序合并分片,不能直接按接收顺序合并 - 可以给每个分片加上文件的唯一标识(比如文件哈希),避免同文件名的文件合并出错
- 大文件上传建议加上进度条,通过
xhr.upload.onprogress来监听单分片或整体上传进度
内容的提问来源于stack exchange,提问作者Mopo
相关产品推荐
相关产品推荐

