JS分片上传音频文件至服务器仅上传开头部分问题求助
文件上传不完整问题排查与解决
核心问题分析
从你的代码和测试结果来看,导致文件上传后仅保留开头部分的原因主要有以下几点:
- 函数参数不匹配:
uploadFile调用uploadChunk时传入了channelId,但uploadChunk未接收该参数,服务器无法正确关联分片到目标文件/频道,导致分片丢失或合并错误。 - 无上传错误处理:
fetch请求失败时未中断流程,分片丢失后仍继续上传,最终合并的文件缺失部分数据。 - JSON payload大小限制:500KB的原始分片转base64后约667KB,部分服务器对JSON格式的POST请求有大小限制,导致分片被截断。
- base64转换的冗余风险:转base64会增加33%的体积,既降低传输效率,也更容易触发服务器的大小限制。
针对性解决方法
1. 修复参数传递与错误处理
修改uploadChunk,补全参数并添加错误捕获,确保分片上传失败时能及时中断流程:
async function uploadChunk(chunk, channelId) { return new Promise((resolve, reject) => { setTimeout(() => { console.log(`Uploading chunk: ${chunk.substring(0, 25)}...`); fetch(`/upload/${currentUID}`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ chunk, channelId }) }) .then(res => { if (!res.ok) throw new Error(`上传失败,状态码:${res.status}`); return res.json(); }) .then(data => resolve(data)) .catch(err => { console.error('分片上传出错:', err); reject(err); }) }, 50); }); }
2. 改用FormData上传(推荐)
放弃base64转换,直接上传原始Blob分片,避免JSON大小限制,同时提升传输效率:
// 重写uploadChunk,使用FormData async function uploadChunk(chunk, channelId) { return new Promise((resolve, reject) => { setTimeout(() => { const formData = new FormData(); formData.append('chunk', chunk); formData.append('channelId', channelId); formData.append('uid', currentUID); fetch(`/upload/${currentUID}`, { method: "POST", body: formData // 浏览器自动处理Content-Type }) .then(res => { if (!res.ok) throw new Error(`上传失败,状态码:${res.status}`); return res.json(); }) .then(data => resolve(data)) .catch(err => reject(err)); }, 50); }); } // 简化uploadFile,无需转base64 async function uploadFile(file) { const chunkSize = 500 * 1024; let currentPosition = 0; currentUID = generateUID(); try { while (currentPosition < file.size) { const chunk = file.slice(currentPosition, currentPosition + chunkSize); currentPosition += chunk.size; await uploadChunk(chunk, channelId); // 进度更新代码... } // 所有分片上传完成后,通知服务器合并 await fetch(`/merge/${currentUID}`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ channelId, fileName: file.name }) }); } catch (err) { console.error('文件上传失败:', err); // 这里可以添加重试逻辑或提示用户 } }
3. 验证分片完整性
在uploadFile中添加日志,确认每个分片的大小和base64长度(如果继续使用base64方案):
while (currentPosition < file.size) { const chunk = file.slice(currentPosition, currentPosition + chunkSize); console.log(`处理分片:起始位置${currentPosition},大小${chunk.size}`); currentPosition += chunk.size; const base64Chunk = await readChunkAsBase64(chunk); console.log(`分片base64长度:${base64Chunk.length}`); await uploadChunk(base64Chunk, channelId); // 进度更新代码... } console.log('所有分片处理完成,最终位置:', currentPosition);
4. 检查服务器配置
确认服务器端是否有请求大小限制:
- Node.js(Express):检查
body-parser的limit配置,或改用multer处理FormData - Nginx:修改
client_max_body_size参数,确保能容纳分片大小
内容的提问来源于stack exchange,提问作者ghosty
相关产品推荐
相关产品推荐

