在分片上传过程中,由于网络传输的不稳定性,可能会出现上传失败的情况。当某个文件块上传失败时,代码中使用的是 catch 方法来捕获错误,并输出错误信息。但是在出现错误时,并不会中断循环,而是机械地将 finished 变量加一并判断是否所有块都已上传完成,这样就会导致文件块的索引错乱。
为了解决这个问题,需要对上传过程进行改进。可以使用 async/await 来实现异步处理,从而使上传过程变得更为顺畅。代码示例如下:
async function uploadChunks(file, url) {
const chunkSize = 2 * 1024 * 1024; // 每个文件块的大小(2MB)
const total = Math.ceil(file.size / chunkSize); // 总块数
const md5 = await getMD5(file); // 获取文件的 MD5 值
let uploaded = 0; // 已上传的块数
let responses = []; // 存储每个块上传成功后返回的数据
// 切分文件并上传
for (let i = 0; i < total; i++) {
const start = i * chunkSize;
const end = Math.min(file.size, (i + 1) * chunkSize);
const formData = new FormData();
formData.append("file", file.slice(start, end));
formData.append("name", file.name);
formData.append("index", i + 1);
formData.append("total", total);
formData.append("md5", md5);
` try {
const res = await upload(formData, {
onUploadProgress: (e) => {
const { loaded, total } = e;
const percent = Math.floor((loaded / total) * 100);
console.log(`第${i + 1}块上传进度:${percent}%`);
},
});
console.log(`第${i + 1}块上传成功`);
uploaded++;
responses[i] = res;
} catch (err) {
console.log(`第${i + 1}块上传失败:${err}`);
}`
}
// 检查所有块是否上传成功
if (uploaded < total) {
console.error(`上传失败:只上传了${uploaded}个块`);
return;
}
// 所有块上传成功,开始合并文件
const mergedRes = await mergeChunks(file, url, responses);
console.log(`合并结果:`, mergedRes);
}
// 按顺序合并文件块
async function mergeChunks(file, url, responses) {
const formData = new FormData();
formData.append("name", file.name);
formData.append("total", responses.length);
const responseArray = responses.sort((a, b) => a.index - b.index);
const blob = await new Response(
new Blob(responseArray.map((res) => res.data))
).blob();
formData.append("file", blob);
return upload(formData);
}
总结来说,应该在每个上传块的上传过程中进行错误处理,并阻止上传块循环。在所有文件块都上传成功时,再进行文件合并操作。