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

如何对S3的getSignedUrl生成的签名URL执行pipe流式传输

解决方案

核心原因

你遇到的报错本质是两个API的返回值类型完全不同:

  • s3.getObject() 返回AWS SDK封装的S3请求实例,内置createReadStream()方法用来生成读取流
  • getSignedUrlPromise() 最终返回的是字符串格式的预签名HTTP URL,不是S3请求实例,自然不存在createReadStream方法

实现方式

拿到预签名URL后,用Node.js的HTTP客户端向该URL发起GET请求,拿到响应流后即可执行pipe操作,以下是两种常见实现方案:

方案1:使用Node.js原生https模块(无额外依赖)

const https = require('https');
const AWS = require('aws-sdk');
const s3 = new AWS.S3();

app.get("/images/:key", async (req, res) => {
  try {
    const key = req.params.key;
    const downloadParams = {
      Key: key,
      Bucket: bucketName,
      Expires: 60 // 签名URL有效期,单位秒,可自定义
    };
    // 1. 获取预签名URL
    const signedUrl = await s3.getSignedUrlPromise("getObject", downloadParams);
    // 2. 发起GET请求获取响应流
    https.get(signedUrl, (s3Res) => {
      // 可选:把S3响应的头透传给客户端,比如Content-Type、Content-Length等
      res.set({
        'Content-Type': s3Res.headers['content-type'],
        'Content-Length': s3Res.headers['content-length'],
        'Cache-Control': s3Res.headers['cache-control']
      });
      // 3. 流式传输到客户端响应
      s3Res.pipe(res);
    }).on('error', (err) => {
      console.error('请求签名URL失败:', err);
      res.status(500).send('资源加载失败');
    });
  } catch (err) {
    console.error('生成签名URL失败:', err);
    res.status(500).send('生成访问链接失败');
  }
});

方案2:使用axios(需要先安装axios依赖)

const axios = require('axios');
const AWS = require('aws-sdk');
const s3 = new AWS.S3();

app.get("/images/:key", async (req, res) => {
  try {
    const key = req.params.key;
    const downloadParams = {
      Key: key,
      Bucket: bucketName,
      Expires: 60
    };
    const signedUrl = await s3.getSignedUrlPromise("getObject", downloadParams);
    // 指定responseType为stream获取响应流
    const s3Res = await axios.get(signedUrl, { responseType: 'stream' });
    // 透传响应头
    res.set(s3Res.headers);
    // 流式传输
    s3Res.data.pipe(res);
  } catch (err) {
    console.error('操作失败:', err);
    res.status(500).send('资源加载失败');
  }
});

补充说明

  • 建议透传S3返回的响应头,避免图片格式、缓存策略等异常
  • 需要给流添加error事件监听,避免网络异常导致服务进程崩溃
  • 如果你只是要给客户端返回S3资源,也可以直接把生成的签名URL返回给前端,让前端直接跳转/加载该URL,不需要经过你的服务端中转流式传输,能节省服务端带宽。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 18:45:03