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

Cloud Run(Node.js)下载GCS对象遇‘cannot read property of null’错误求助

Cloud Run(Node.js)中GCS对象流式写入/tmp失败,但内存缓存写入正常

我在运行Node.js的Google Cloud Run服务里,尝试把Google Cloud Storage(GCS)的对象下载到/tmp目录,按照官方教程写了如下代码:

exports.resizeImage = async (eventData) => {
  const file = storage.bucket(eventData.bucket).file(eventData.name);

  // 解析图片扩展名
  const [metadata] = await file.getMetadata();
  const extension = metadataContentTypeToExtension(metadata.contentType);

  const tempLocalPath = `/tmp/${path.parse(file.name).base}.${extension}`;

  console.log(tempLocalPath); // 输出 "/tmp/clpeytui4003nfcsjqjyifk0d.jpg"

  try {
    // 测试是否正确定位到对象
    const url = await file.getSignedUrl({
      action: 'read',
      expires: '03-17-2025',
    });
    console.log(`访问URL: ${url}`);
  } catch (err) {
    console.error('无法获取预签名URL:');
    console.error(err);
  }

  // 从存储桶下载文件
  try {
    console.log(`正在下载 ${file.name} 到 ${tempLocalPath}...`);
    const dlPromise = file.download({ destination: tempLocalPath });
    dlPromise.catch((err) => {
      console.error('下载失败(Promise捕获).');
      console.error(err);
    });
  } catch (err) {
    console.error(`文件下载失败: ${err}`);
    return;
  }
}

Cloud Run日志里出现错误:Error: read ECONNRESET,报错位置在底层的stream-shift调用中。

预签名URL可以在浏览器正常访问,说明文件定位没问题,而且已经给服务分配了storage.admin权限。我猜测是获取下载数据流时出了问题,于是尝试自定义下载函数:

const downloadFile = (file, downloadPath) =>
  new Promise((resolve, reject) => {
    console.log('尝试下载文件...');
    file
      .createReadStream()
      .pipe(fs.createWriteStream(downloadPath))
      .on('finish', () => {
        console.log(`图片已下载到本地路径 ${downloadPath}`);
        console.log(`文件大小: ${fs.statSync(downloadPath).size} 字节`);
        resolve();
      })
      .on('error', (err) => {
        console.error('文件下载失败.', err);
        reject(err);
      });
  });

但还是出现同样的底层stream-shift错误,而且自定义的错误日志根本没触发。

11/26更新:我把.pipe(fs.createWriteStream(downloadPath))替换成自己实现的内存缓存数据方式后,问题解决了:

const downloadFile = (file, downloadPath) =>
  new Promise((resolve, reject) => {
    const buffer = [];
    file
      .createReadStream()
      // .pipe(fs.createWriteStream(downloadPath)) // 有问题的代码行
      .on('data', (chunk) => {
        buffer.push(chunk);
      })
      .on('finish', () => {
        fs.writeFileSync(downloadPath, Buffer.concat(buffer));
        resolve();
      })
      .on('error', (err) => {
        console.error('文件下载失败.', err);
        reject(err);
      });
  });

(已验证下载的文件和原文件完全一致)

问题显然出在流式写入而非缓存写入的方式上,我搞不懂为什么官方教程提供的代码没法正确处理流式写入,求解决方案。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 12:22:18