JavaScript中blob.slice()返回空Blob问题(大文件分片上传场景)
解决
blob.slice()返回空Blob的问题 我来帮你搞定这个大文件分片传输里的空Blob问题,这是分片传输中很常见的坑,咱们从最可能的原因开始排查:
最常见的错误:切片参数搞反了
File.slice()(Blob的子类)的第二个参数是切片的结束位置,不是切片的长度!你的代码里直接传了expectedSize,如果offset已经大于expectedSize,或者expectedSize不是相对于offset的增量,就会出现结束位置小于起始位置的情况,这时候浏览器就会返回空Blob。
修正方案
把结束位置计算为offset + expectedSize,同时确保不超过文件总大小:
const end = Math.min(offset + expectedSize, file.size); const blobChunk = file.slice(offset, end);
提前终止无效的切片请求
你的代码里判断了offset > file.size,但如果offset等于文件大小,切片同样会返回空Blob。建议改成:
if (offset >= file.size) { // 文件已经传输完成,直接返回 console.log("传输完成,无需继续切片"); return; }
另外还要检查expectedSize是否为正数,如果是0或者负数,切片也会返回空Blob:
if (progressModel.ExpectedChunkSize <= 0) { throw new Error("分片大小必须是正数"); }
旧浏览器兼容性处理(可选)
虽然现代浏览器都支持标准的slice,但如果你的应用需要兼容旧版Firefox/Chrome,可以做个兼容处理:
const sliceFn = file.slice || (file as any).mozSlice || (file as any).webkitSlice; const blobChunk = sliceFn.call(file, offset, end);
调试建议
在切片后加个日志,确认参数和切片结果是否正常:
console.log(`切片参数:offset=${offset}, end=${end}, 文件大小=${file.size}`); console.log(`切片结果大小:${blobChunk.size}`);
如果切片大小还是0,那大概率是progressModel里的Offset或者ExpectedChunkSize值有问题,比如Offset没有正确累加已传输的分片大小。
修正后的完整代码示例
private readonly sendChunk = (file: File, progressModel: ProgressResponseModel): void => { const offset = progressModel.Offset; const expectedSize = progressModel.ExpectedChunkSize; // 校验参数合法性 if (offset >= file.size) { console.log("文件传输已完成"); return; } if (offset < 0) { throw new Error("偏移量不能为负数"); } if (expectedSize <= 0) { throw new Error("分片大小必须为正数"); } // 计算正确的切片结束位置 const end = Math.min(offset + expectedSize, file.size); // 兼容旧浏览器的切片方法 const sliceFn = file.slice || (file as any).mozSlice || (file as any).webkitSlice; const blobChunk = sliceFn.call(file, offset, end); // 检查切片是否有效 if (blobChunk.size === 0) { console.error(`切片失败:offset=${offset}, end=${end}, 文件大小=${file.size}`); return; } const xhr = new XMLHttpRequest(); xhr.onload = (ev: Event) => { // 这里写你的加载完成逻辑 }; // 后续XHR配置、发送分片的逻辑... };
内容的提问来源于stack exchange,提问作者Martin Shishkov
相关产品推荐
相关产品推荐

