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

Node.js调用Google Drive API v3下载大文件无法获取进度

解决Google Drive大文件下载时无法触发data事件获取进度的问题

你的问题核心在于没有使用流式传输模式,同时对Google Drive SDK的响应处理方式理解有误。让我一步步帮你梳理并修正:

问题分析

  1. responseType: "arraybuffer"的问题:当你设置这个参数时,SDK会把整个文件内容一次性加载到内存中,生成一个完整的ArrayBuffer后才会调用回调。这就意味着不会触发data事件——因为没有分块传输,自然没有分段数据可以监听。
  2. 事件监听位置错误:你把data.on('data')写在fs.writeFile的回调里,这时候data已经是完整的buffer了,根本不是一个可读流,当然不会有data事件触发。

正确实现方式

要实现大文件的流式下载并获取进度,你需要:

  • 将responseType设置为stream,让SDK返回一个可读流
  • 使用fs.createWriteStream来流式写入文件,避免一次性加载大文件到内存
  • 监听可读流的data事件来计算下载进度,同时监听end和error事件处理完成与异常情况

修正后的代码如下:

const downloadFile = (file) => {
  const fileId = file.id;
  const fileName = path.join(basePathForStorage, file.name);
  const drive = google.drive({ version: 'v3', authorization });
  let progress = 0;
  let totalSize = 0;

  return new Promise((resolve, reject) => {
    drive.files.get(
      {
        auth: authorization,
        fileId: fileId,
        alt: 'media'
      },
      { responseType: "stream" }, // 关键:使用stream类型
      function (err, response) {
        if (err) {
          console.error('下载请求失败:', err);
          return reject(err);
        }

        // 从响应头获取文件总大小
        totalSize = parseInt(response.headers['content-length'], 10);
        const writeStream = fs.createWriteStream(fileName);

        // 监听data事件计算进度
        response.data.on('data', (chunk) => {
          progress += chunk.length;
          const progressPercent = ((progress / totalSize) * 100).toFixed(2);
          console.log(`下载进度: ${progressPercent}% (${progress}/${totalSize} bytes)`);
        });

        // 处理流的错误
        response.data.on('error', (streamErr) => {
          console.error('下载流错误:', streamErr);
          writeStream.close();
          fs.unlinkSync(fileName); // 出错时删除已下载的部分文件
          reject(streamErr);
        });

        // 流结束时完成Promise
        response.data.on('end', () => {
          console.log('文件下载完成:', fileName);
          resolve(fileName);
        });

        // 将下载流管道到写入流
        response.data.pipe(writeStream);
      }
    );
  });
};

关键要点说明

  • 流式传输的优势:对于大文件来说,流式传输不会把整个文件加载到内存,而是分块处理,避免内存溢出问题,同时能实时获取下载进度。
  • content-length的使用:通过响应头的content-length字段可以获取文件总大小,这样就能计算出百分比进度。注意如果文件是动态生成的(比如Google Drive的某些特殊文件),这个字段可能不存在,这时候可以只显示已下载的字节数。
  • 错误处理:要同时监听请求错误和流的错误,并且在出错时清理已下载的文件,避免生成损坏的文件。

这样修改后,你就能正常触发data事件,实时看到下载进度了!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:24:35