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

如何从S3图片流提取MIME类型并按类型命名写入磁盘?

解决方案:通过PassThrough流缓存数据,先获取格式再写入正确文件

你的核心问题在于:创建写入流时还没拿到图片格式,导致没法动态修改文件名。使用PassThrough流可以先缓存S3返回的图片数据,等拿到格式后再创建正确的写入流完成写入。

下面是修改后的完整代码:

import { S3Client, GetObjectCommand } from "@aws-sdk/client-s3";
import { createWriteStream } from "fs";
import { Readable, PassThrough } from "stream";
import sharp from "sharp";

async function retrieveAsset(
  bucket: string,
  asset: string,
  destination: string
) {
  const client = new S3Client({
    region: "auto",
    endpoint: `https://${ACCOUNT_ID}.r2.cloudflarestorage.com`,
    credentials: {
      accessKeyId: ACCESS_KEY_ID,
      secretAccessKey: SECRET_ACCESS_KEY,
    },
  });

  const response = await client.send(
    new GetObjectCommand({ Bucket: bucket, Key: asset })
  );

  const body = response.Body;
  if (!(body instanceof Readable)) {
    throw new Error("响应体不是可读流");
  }

  // 1. 创建PassThrough流缓存图片数据,避免直接写入丢失
  const passThrough = new PassThrough();
  body.pipe(passThrough);

  // 2. 用sharp获取图片元数据,拿到格式信息
  const meta = await sharp(passThrough).metadata();
  if (!meta.format) {
    throw new Error("无法识别图片格式");
  }

  // 3. 拼接最终文件名
  const finalDestination = `${destination}.${meta.format}`;
  const writeStream = createWriteStream(finalDestination);

  // 4. 重置PassThrough流,重新导向到写入流
  passThrough.unpipe();
  passThrough.pipe(writeStream);

  // 5. 处理流的完成与错误事件
  return new Promise((resolve, reject) => {
    writeStream.on("error", reject);
    writeStream.on("finish", resolve);
    passThrough.on("error", reject);
  });
}

关键逻辑说明

  • PassThrough流的作用:作为数据缓存中间层,先接收S3返回的图片流,避免直接写入文件时还没拿到格式信息。
  • 先获取格式再写入:通过sharp().metadata()异步获取图片格式,拿到后再拼接正确的文件名,创建写入流。
  • 重置流管道:因为sharp已经读取了PassThrough的部分数据,所以需要先解除之前的管道,重新将PassThrough导向新创建的写入流,确保所有数据都能写入文件。

调用示例:

retrieveAsset("test", "test.jpg", "newtest");

会生成文件newtest.jpg,完全符合你的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 09:15:08