NodeJS使用@aws-sdk/client-s3 v3如何将S3文件通过API返回供下载
你之前调用pipe失败的核心原因是awsCtrl.getObject返回的是完整的S3响应对象,可读流实际存储在该对象的Body属性中,你直接对整个响应对象调用pipe当然不会生效。
下面是修改后的可正常运行的代码,全程采用流传输,不会将文件写入服务端本地磁盘,完全符合你的需求:
const { Readable } = require('stream'); // 低版本SDK需要用到,版本较新可省略 filesCtrl.deliverFile = async (req, res) => { // 补充获取实际S3文件路径和下载文件名的逻辑,以下为示例 const filePath = req.params.fileId; const filename = "自定义下载文件名"; const result = {}; /* Get object from AWS S3 */ let s3Response; try { s3Response = await awsCtrl.getObject(filePath); } catch (e) { consoleLogger.error(`Unable to get object from AWS S3`, e); if (e.status && e.status === 404) { result.error = `Not found`; return res.status(404).json(result); } return res.status(e.status || 500).json(result); } // 设置下载响应头 res.attachment(filename); // 复用S3返回的文件类型,避免客户端识别错误 res.setHeader('Content-Type', s3Response.ContentType || 'application/octet-stream'); // 可选配置Content-Length,方便客户端显示下载进度 if (s3Response.ContentLength) { res.setHeader('Content-Length', s3Response.ContentLength); } // 提取S3返回的文件流 let fileStream = s3Response.Body; // 低版本SDK返回Web Stream的话,用以下代码转成Node.js可读流,版本较新可省略 // fileStream = Readable.fromWeb(fileStream); // 流传输到客户端 fileStream.pipe(res); // 监听流传输错误,避免服务崩溃 fileStream.on('error', (err) => { consoleLogger.error('File stream error:', err); if (!res.headersSent) { res.status(500).json({ error: 'File download failed' }); } }); }
注意事项
- 如果你的
@aws-sdk/client-s3版本≥3.180.0,Node环境下默认返回的Body就是Node.js可读流,不需要额外做格式转换 - 传输过程中服务端仅做流转发,不会缓存完整文件,资源占用极低
内容的提问来源于stack exchange,提问作者pengz
相关产品推荐
相关产品推荐

