You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 07:47:13