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

Node.js中如何向Google Cloud Storage上报上传进度

实现Google Cloud Storage文件上传进度追踪

你原来尝试监听的data事件是Node.js Readable流的事件,而@google-cloud/storage的createWriteStream返回的是Writable流,所以不会触发。该库实际支持上传进度的监听,主要有两种可靠的实现方式,下面结合你的现有代码给出具体方案:

方式1:使用官方提供的onProgress回调(推荐)

在调用createWriteStream时,可以传入配置参数,其中onProgress会在上传过程中被定期调用,回调参数里包含已上传字节数和总字节数,直接用来计算进度即可。

修改后的完整代码:

router.post("/upload-file", multer.single("file"), async (req, res, next) => {
    try{
        const file = req.file;
        if (!file) {
            return res.status(400).json({ message: "No file uploaded" });
        }

        const folderPath = `Files/`;
        const fileName = folderPath + file.originalname;
        const blob = retmBucket.file(fileName);
        
        // 创建写入流时传入onProgress配置
        const blobStream = blob.createWriteStream({
            onProgress: (progressEvent) => {
                const percent = (progressEvent.bytesWritten / progressEvent.totalBytes) * 100;
                console.log(`上传进度: ${percent.toFixed(2)}%`);
                // 若要向客户端实时推送进度,推荐用SSE(Server-Sent Events)
                res.write(`data: ${JSON.stringify({ progress: percent.toFixed(2) })}\n\n`);
            }
        });

        blobStream.on("error", (error) => {
            res.status(500).json({
                message: "Error during file upload!",
                error: error.message
            });
        });
        
        blobStream.on("finish", async () => {
            // 结束SSE响应并返回最终结果
            res.end(JSON.stringify({
                message: "File has been uploaded successfully",
                data: fileName
            }));
        });

        blobStream.end(file.buffer);

    }catch(error){
        res.status(409).json({
            message: "Error during file upload!",
            error: error.message
        })
    }
})

方式2:手动跟踪写入字节数

如果需要更灵活的控制,也可以通过分块写入并监听Writable流的drain事件,结合已写入字节数计算进度:

router.post("/upload-file", multer.single("file"), async (req, res, next) => {
    try{
        const file = req.file;
        if (!file) {
            return res.status(400).json({ message: "No file uploaded" });
        }

        const folderPath = `Files/`;
        const fileName = folderPath + file.originalname;
        const blob = retmBucket.file(fileName);
        const blobStream = blob.createWriteStream();

        let bytesWritten = 0;
        const totalBytes = file.size;
        const chunkSize = 1024 * 1024; // 按1MB分块写入

        // 监听缓冲区排空事件,更新进度
        blobStream.on("drain", () => {
            const percent = (bytesWritten / totalBytes) * 100;
            console.log(`上传进度: ${percent.toFixed(2)}%`);
            // 同样可通过SSE推送进度给客户端
        });

        // 分块写入逻辑
        let offset = 0;
        function writeChunk() {
            while (offset < totalBytes) {
                const chunk = file.buffer.slice(offset, offset + chunkSize);
                bytesWritten += chunk.length;
                offset += chunkSize;
                // 缓冲区满时停止写入,等待drain事件
                if (!blobStream.write(chunk)) {
                    blobStream.once("drain", writeChunk);
                    return;
                }
            }
            blobStream.end();
        }
        writeChunk();

        blobStream.on("error", (error) => {
            res.status(500).json({
                message: "Error during file upload!",
                error: error.message
            });
        });
        
        blobStream.on("finish", async () => {
            res.status(200).json({
                message: "File has been uploaded successfully",
                data: fileName
            })
        });

    }catch(error){
        res.status(409).json({
            message: "Error during file upload!",
            error: error.message
        })
    }
})

关键注意事项

  • 向客户端实时上报进度时,普通HTTP响应只能发送一次结果,因此推荐使用Server-Sent Events(SSE)或WebSocket实现实时推送,上述代码已示例SSE的基础写法。
  • 确保retmBucket是已正确初始化的Google Cloud Storage Bucket实例。
  • 第一种方式的onProgress是库封装的官方实现,已处理分块上传的进度计算,比手动跟踪更可靠。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 22:23:34