如何使用aws-sdk v3保存S3中的文件



使用新的aws-sdk v3,特别是@aws-sdk/client-s3,我不清楚如何将文件从S3存储到磁盘。
具有以下代码

const { Body } = await s3.send(new GetObjectCommand({
Bucket: 'myBucket',
Key: 'myKey',
}))

Body可以是Readable | ReadableStream | Blob类型
我想把它存储到磁盘上的一个文件中。由于返回类型完全不同,有没有一种简单的方法可以从aws-sdk获得BufferStream.Readable

在aws-sdk v2中,使用似乎已不存在的.createReadStream()函数很容易。

ReadableStream | Blob似乎仅在浏览器中可用。Node.js总是得到Readable,这正是我所需要的。

之后,使用fs.createWriteStream和管道Readable(如(,解决方案非常简单

await new Promise((resolve, reject) => {
Body.pipe(fs.createWriteStream(filePath))
.on('error', err => reject(err))
.on('close', () => resolve())
})

作为参考,这里有一个讨论文档改进的问题https://github.com/aws/aws-sdk-js-v3/issues/1877

要在typescript中执行此操作,还可以执行

await new Promise((resolve, reject) => {
if (Body instanceof Readable) {
Body.pipe(fs.createWriteStream(filePath))
.on('error', err => reject(err))
.on('close', () => resolve())
}
});

GetObjectCommand返回可读流,我们使用fs模块创建writeStream,并将返回的readableStream从GetObjectCommand传递给writeStream以保存文件

const fs = require('fs');
const { S3Client, GetObjectCommand } = require('@aws-sdk/client-s3');
const s3Client = new S3Client({
region: 'your_region',
credentials: { accessKeyId: 'your_accessKeyId', secretAccessKey: 'your_secretAccessKey' },
});
const bucketParams = {
Bucket: 'your_bucket',
Key: 'your_key.jpg',
};
const run = async () => {
try {
const data = await s3Client.send(new GetObjectCommand(bucketParams));
const inputStream = data.Body;
const downloadPath = 'example.png';
const outputStream = fs.createWriteStream(downloadPath);
inputStream.pipe(outputStream);
outputStream.on('finish', () => {
console.log(`downloaded the file successfully`);
});
} catch (err) {
console.log('Error', err);
}
};

您可以使用上面响应中提到的流式方法,但也可以只使用fs/promises库中的writeFile方法:

const { writeFile } = require("node:fs/promises");
const { S3Client, GetObjectCommand } = require("@aws-sdk/client-s3");
const downloadFile = async () => {
const command = new GetObjectCommand({ Bucket, Key });
const { Body } = await client.send(command);
const localFilename = "path_to_where_to_save_file";
await writeFile(localFilename, Body);
}

然后调用此函数。

我认为这是从node版本v14.18.0开始的,因为此方法接受流作为输入。

最新更新