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

18

使用新的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() 函数非常容易,但该函数似乎已不再存在。


2
请查看此问题 https://github.com/aws/aws-sdk-js-v3/issues/1096#issuecomment-620900466 - Alex Po
4个回答

16

看起来 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,请查看Abigail Nguyen的增强功能。 - Joseph Siefers

4

要在TypeScript中做到这一点,您也可以执行以下操作:

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

2
请注意,您可能需要导入import { Readable } from 'stream' - Joseph Siefers

2

GetObjectCommand returns readable stream, we use fs module to create writeStream and pass the returned readableStream from GetObjectCommand to writeStream to save the file

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);
  }
};


2

你可以使用上面回答中提到的流方法,但也可以直接使用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开始的,因为该方法接受流作为输入。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接