如果我理解正确,您希望从 s3 存储桶中获取对象并作为流传输到您的 HTTP 响应。
与其在缓冲区中获取数据并找出将其转换为流的方法可能会很复杂并且有其局限性,如果您真的想利用流的力量,那么不要尝试将其转换为缓冲区并将整个对象加载到内存中,您可以创建一个请求,通过在请求上调用 createReadStream 方法将返回的数据直接流式传输到 Node.js Stream 对象。
调用 createReadStream 返回请求管理的原始 HTTP 流。然后可以将原始数据流通过管道传输到任何 Node.js Stream 对象中。
此技术对于在其负载中返回原始数据的服务调用很有用,例如在 Amazon S3 服务对象上调用 getObject 以将数据直接流式传输到文件中,如本示例所示。
//I Imagine you have something similar.
server.get ('/image', (req, res) => {
let s3 = new AWS.S3({apiVersion: '2006-03-01'});
let params = {Bucket: 'myBucket', Key: 'myImageFile.jpg'};
let readStream= s3.getObject(params).createReadStream();
// When the stream is done being read, end the response
readStream.on('close', () => {
res.end()
})
readStream.pipe(res);
});
当您使用 createReadStream 从请求中流式传输数据时,只会返回原始 HTTP 数据。 SDK不对数据进行后处理,可以直接返回这个原始的HTTP数据。
注意:
因为 Node.js 无法回退大多数流,如果请求最初成功,则对其余响应禁用重试逻辑。如果套接字失败,在流式传输时,SDK 不会尝试重试或向流发送更多数据。您的应用程序逻辑需要识别此类流式传输故障并进行处理。
修改:
在对原始问题进行编辑后,我可以看到 s3 发送了一个与 Nodejs 中的 FileStream 不同的 PassThrough 流对象。所以要解决这个问题,请使用内存(如果您的文件不是很大并且或者您有足够的内存)。
使用包memfs,它将替换您应用中的原生fs
https://www.npmjs.com/package/memfs
通过npm install memfs安装包,要求如下:
const {fs} = require('memfs');
你的代码看起来像
static async downloadFile(Bucket, Key) {
const result = await s3
.getObject({
Bucket,
Key
})
.promise();
fs.writeFileSync(`/${Key}`,result.Body);
const file = await fs.createReadStream(`/${Key}`);
return file;
}
请注意,我对您的函数所做的唯一更改是将路径 ${Path.basename(Key)} 更改为 /${Key},因为现在您不需要知道我们将文件存储在内存中的原始文件系统的路径.我已经测试过,这个解决方案有效