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

XHR onreadystatechange内的for循环无法执行问题排查

Google Drive可恢复上传分块循环不执行的问题修复

核心问题及修复步骤

  • 循环被提前终止:你在for循环的第一次迭代里就执行了return res.status(200).json(...),这会直接跳出整个onreadystatechange回调函数,循环根本没机会继续执行。要把这个响应返回逻辑移到所有分块上传完成之后,要是需要实时返回进度,得用SSE这类方式,不能直接返回响应终止流程。
  • 分块范围取值错误:循环里写fileChunks.start和fileChunks.end是错的,fileChunks是数组,每个分块的起止应该对应fileChunks[i].start和fileChunks[i].end,不然拿不到当前循环的分块数据范围。
  • 异步请求未按顺序处理:Google Drive的可恢复上传要求分块按顺序上传,不能并行发起请求。你现在的写法是循环里直接批量发起axios请求,会导致乱序,应该用async/await等待每个分块上传完成后再处理下一个。
  • 分块数据未正确传入:代码里的buffer变量没有定义,应该传入当前分块的buffer,比如fileChunks[i].data,再转成流。

修正后的代码示例

xhr.onreadystatechange = async function () {
    if (this.readyState == this.HEADERS_RECEIVED) {
        // 解析响应头获取可恢复上传URI
        var headers = xhr.getAllResponseHeaders();
        var arr = headers.trim().split(/[\r\n]+/);
        var headerMap = {};
        arr.forEach(function (line) {
            var parts = line.split(": ");
            var header = parts.shift();
            var value = parts.join(": ");
            headerMap[header] = value;
        });
        const resumableURI = headerMap.location;
        console.log('resumable uri : ' + resumableURI);
        const fileChunks = divideFileInChunks(req.files.muploadedFile.data);
        const totalChunks = fileChunks.length;

        try {
            for (let i = 0; i < totalChunks; i++) {
                console.log(`正在上传第 ${i+1} 块,共 ${totalChunks} 块`);
                // 获取当前分块的信息
                const chunk = fileChunks[i];
                // 发起分块上传请求,用await等待完成
                const resp = await axios.put(resumableURI, bufferToStream(chunk.data), {
                    headers: {
                        Authorization: `Bearer ${accessToken}`,
                        "Content-Length": chunk.end - chunk.start + 1, // 当前分块的实际大小
                        "Content-Range": `bytes ${chunk.start}-${chunk.end}/${req.files.muploadedFile.size}`
                    }
                });
                console.log(`第 ${i+1} 块上传完成`, resp.data);
            }
            // 所有分块上传完成后再返回响应
            return res.status(200).json({message: `所有 ${totalChunks} 块已上传完成`});
        } catch (f) {
            console.error('上传失败', f);
            res.status(500).send(f.message);
        }
    }
};

xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
xhr.setRequestHeader("Authorization", `Bearer ${accessToken}`);
xhr.send(
    JSON.stringify({
        name: req.files.muploadedFile.name,
        mimeType: req.files.muploadedFile.mimetype,
    })
);

额外注意事项

  • 确保divideFileInChunks函数返回的每个分块对象包含start(起始字节)、end(结束字节)、data(分块的buffer数据)三个核心属性。
  • 如果需要实时给客户端推送上传进度,不能用一次性HTTP响应,应该使用服务器发送事件(SSE)或者WebSocket来逐步更新进度。
  • 要处理分块上传失败的情况,比如某个分块上传失败,需要根据Google Drive API的响应重新发起该分块的上传,不要直接终止整个上传流程。

内容的提问来源于stack exchange,提问作者karthi keyan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 23:54:23