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

Node.js中管道上传多字符串到Amazon S3 Bucket无数据问题排查

问题原因分析
  • 重复调用S3.upload逻辑错误:S3 SDK的upload方法接收流作为Body参数时,需要在流数据推送前仅初始化一次上传任务,让upload全程监听流的数据推送直到流结束。你当前在每次调用to方法时都重新创建一次upload任务,第一次调用to触发的upload只会捕获当前已推送到流的数据,后续to调用推送的数据不会被之前的upload任务接收,且多次upload会互相覆盖同key的对象,最终上传的内容为空或不完整。
  • 流被多次消费导致数据分流:你在每次to方法中都调用this.#stream?.pipe(process.stdout),pipe操作会消费流中的数据,同时S3的upload也在消费同一个流,会导致数据被stdout分流,S3无法拿到完整的流数据。
  • upload等待时机错误:你在每次to方法内就await S3.upload(...).promise(),但流是在finish方法调用推送null后才会标记结束,upload会一直等待流结束才会完成上传,这里会直接阻塞后续的to调用,甚至出现超时情况,永远等不到流结束。
  • 缺少换行分隔符:你当前直接推送字符串s到流中,最终三个字符串会拼接成连续的文本,不会得到每行一条的效果。
修复后的代码示例
export class S3Output extends Output {
  #stream: Readable | null = null
  #uploadPromise: Promise<void> | null = null

  async to(s: string): Promise<void> {
    // 推送时加换行符分隔
    this.#stream?.push(s + '\n')
  }

  init(): void {
    this.#stream = new Readable()
    this.#stream._read = function () {};
    // 初始化阶段就创建一次upload任务,全程监听流
    const params = {
      Bucket: config.aws.bucketName,
      Body: this.#stream,
      Key: 'test.json'
    }
    // 流需要输出到stdout的话,在这里只pipe一次
    this.#stream.pipe(process.stdout)
    // 存储upload的promise,留到finish时等待
    this.#uploadPromise = S3.upload(params).promise()
  }

  async finish(): Promise<void> {
    // 推送null标记流结束
    this.#stream?.push(null)
    // 等待上传完成
    await this.#uploadPromise
    return
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 07:48:02