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

使用Node.js/TypeScript调用GCS的createWriteStream时遇ApiError: Not Found

解决GCS createWriteStream 出现「ApiError: Not Found」的问题

问题分析

你遇到的核心矛盾是:代码中指定了正确的bucket和文件名,打印验证也显示值正确,但实际请求URL却错误地将{organizationId}/orders.csv当作bucket名,导致资源找不到。这种情况通常不是代码逻辑的直接问题,而是Storage实例配置、SDK缓存或版本bug导致的路径解析异常。

排查与解决方案

1. 检查Storage实例的初始化

首先确认this.storage的创建过程是否正确,有没有误设置默认bucket或者错误的项目配置:

// 正确的初始化方式(无错误默认配置)
import { Storage } from '@google-cloud/storage';

this.storage = new Storage({
  // 仅在需要时配置认证信息,比如服务账号密钥
  // keyFilename: './service-account-key.json'
});
  • 避免在初始化时传入defaultBucket参数,否则会覆盖你后续指定的bucketName
  • 检查环境变量中是否存在GOOGLE_CLOUD_STORAGE_BUCKET,这个变量会被SDK作为默认bucket使用

2. 验证文件的完整路径

在创建newFile后,打印完整路径确认解析是否正确:

const newFile = bucket.file(newFilePath);
console.log('完整文件路径:', newFile.fullName);
// 预期输出:shadowscore-data-import-production/orders.csv

如果输出不符合预期,说明bucket实例本身有问题,大概率是Storage初始化时的配置错误。

3. 升级GCS SDK到最新稳定版

旧版本的@google-cloud/storage(比如v5及更早版本)存在路径解析的bug,可能导致bucket和文件名混淆。执行以下命令升级:

npm install @google-cloud/storage@latest

4. 清除缓存并重启服务

Node.js的模块缓存可能残留旧的配置,导致代码修改后不生效:

  • 重启你的Node.js服务
  • 必要时删除node_modules和package-lock.json,重新执行npm install

5. 确认bucket权限与存在性

虽然错误是「Not Found」,但也可能是权限问题导致的间接报错:

  • 确认shadowscore-data-import-production这个bucket确实存在于你的GCP项目中
  • 确认服务账号拥有storage.objects.create的权限(可在GCP控制台的IAM页面配置)

修正后的完整代码示例

import { Storage } from '@google-cloud/storage';
import { Readable } from 'stream';

class GcsUploadService {
  private storage: Storage;

  constructor() {
    // 初始化Storage,确保无错误配置
    this.storage = new Storage({
      // 按需添加认证信息
      // credentials: require('./service-account.json')
    });
  }

  async uploadStream(stream: Readable): Promise<string> {
    const bucketName = 'shadowscore-data-import-production';
    const bucket = this.storage.bucket(bucketName);
    const newFilePath = 'orders.csv';
    const newFile = bucket.file(newFilePath);

    // 打印验证信息
    console.log('Bucket名称:', bucket.name);
    console.log('文件名称:', newFile.name);
    console.log('完整路径:', newFile.fullName);

    const writeStream = newFile.createWriteStream({
      resumable: false,
    });

    return new Promise((resolve, reject) => {
      stream.on('error', (error) => {
        writeStream.destroy(error);
        reject(error);
      });

      writeStream.on('error', (error) => {
        stream.unpipe();
        reject(error);
      });

      writeStream.on('finish', () => {
        resolve(newFilePath);
      });

      stream.pipe(writeStream);
    });
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 01:02:47