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

如何为stream创建cache或bucket,解决等待文件大小后上传流的write after end错误

报错根因

你代码中触发Error [ERR_STREAM_WRITE_AFTER_END]的核心原因是:http下载流在创建完成后会立刻开始接收响应数据,在await getFileSize的等待过程中,下载流可能已经完成数据接收并自动销毁,后续调用上传方法时操作已结束的流无法再写入/传递数据就会触发该错误。

方案1:调整请求顺序(最优,无额外开销)

如果你的getFileSize是通过HEAD请求获取Content-Length头(不会实际下载文件内容),优先调整执行顺序,先拿文件大小再创建下载流即可:

(async () => {
  // 第一步先获取文件大小
  const filesize = await getFileSize('https://www.google.com/m3u8.mp4');
  // 拿到大小后再创建下载流,直接传入上传SDK
  const video = http('https://www.google.com/m3u8.mp4');
  uploadToCOS(video, filesize);
})();
方案2:PassThrough流内存缓存(小文件适用)

如果业务逻辑要求必须先创建下载流再获取文件大小,可以使用Node.js内置的stream.PassThrough做中转缓存,它是双工流,会将写入的数据暂存在内部缓冲区,直到有消费者接入后再输出数据:

const { PassThrough } = require('stream');

(async () => {
  // 创建中转缓存流
  const cacheStream = new PassThrough();
  // 下载流直接pipe到缓存流,数据会暂存在缓冲区
  const video = http('https://www.google.com/m3u8.mp4');
  video.pipe(cacheStream);

  // 等待获取文件大小
  const filesize = await getFileSize('https://www.google.com/m3u8.mp4');

  // 直接将缓存流传给上传SDK即可
  uploadToCOS(cacheStream, filesize);
})();

注意:该方案仅适合小文件场景,大文件会占用大量内存,甚至触发OOM。

方案3:临时文件缓存(大文件适用)

大文件场景下建议将下载流先写入本地临时文件,拿到文件大小后再读取临时文件流上传,上传完成后删除临时文件即可:

const fs = require('fs');
const path = require('path');

(async () => {
  const tmpFilePath = path.join(__dirname, 'tmp_cache.mp4');
  // 先将下载流写入本地临时文件
  const video = http('https://www.google.com/m3u8.mp4');
  const writeStream = fs.createWriteStream(tmpFilePath);
  video.pipe(writeStream);

  // 等待临时文件写入完成,同时获取文件大小
  const filesize = await new Promise((resolve, reject) => {
    writeStream.on('finish', () => resolve(fs.statSync(tmpFilePath).size));
    writeStream.on('error', reject);
  });

  // 读取临时文件流上传,完成后删除临时文件
  const readStream = fs.createReadStream(tmpFilePath);
  uploadToCOS(readStream, filesize, () => {
    fs.unlinkSync(tmpFilePath);
  });
})();

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 19:45:09