NodeJS 如何从s3存储桶中获取文件阅读流?

suzh9iv8  于 2023-10-17  发布在  Node.js
关注(0)|答案(1)|浏览(134)

我通过axios与外部REST API进行交互。它接受 multipart/form-data 格式的图像作为输入。当我尝试使用以下代码从我的计算机发送时,一切正常!

const formData = new FormData();
formData.append('photo', fs.createReadStream(imgPath));

const uploadImgResult = await request({
  method: 'POST',
  url: upload_url,
  headers: formData.getHeaders(),
  data: formData
});

但现在我面临的任务是从AWS lambda函数执行相同的操作,从s3 Bucket接收图像。我尝试了几个获取读取流的选项,但它们都返回一个不正确的文件类型错误。
根据上面的例子,我明白了,我需要弄清楚如何从文件中以某种格式获取s3,以便将其添加到表单中。以下是我尝试的选项:

// Option 1
this._awsS3 = new AWS.S3({apiVersion: '2006-03-01'});    
const imgObject = await this._awsS3
        .getObject({
            Key: requestParams.key,
            Bucket: 'someBucketName'
         })).promise();

// Option 2
const imgObject = this._awsS3
        .getObject({
            Key: requestParams.key,
            Bucket: 'someBucketName'
         }))
        .createReadStream();

// Option 3
const imgObject await (new Promise(async res => {
        const passThroughStream = new PassThrough();

        this._awsS3
            .getObject({
               Key: requestParams.key,
               Bucket: 'someBucketName'
            })
            .createReadStream().pipe(passThroughStream);

        passThroughStream.on('finish', () => {
            res(passThroughStream);
        }));

重要的是要注意,这些文件是以正确的png图像的形式存储在s3中的(我尝试手动下载它们,它们打开了)。此外,上述所有方法都可以成功地从s3中以一种或另一种形式检索文件。唯一的问题是API端点返回类型错误

a14dhokn

a14dhokn1#

Lambda函数遇到的问题可能与发送到外部REST API的数据的格式或编码有关。在Lambda函数和S3中处理图像时,您需要确保图像数据被正确格式化为multipart/form-data。
这里有一个实现这一点的常见模式:
从S3获取图像。将图像数据转换为可读流。创建一个FormData对象并将图像数据附加到其中。将FormData发送到外部REST API。以下是如何修改Lambda函数代码以遵循此模式:

JavaScript

const AWS = require('aws-sdk');
const FormData = require('form-data');
const axios = require('axios');
const { PassThrough } = require('stream');

const s3 = new AWS.S3();

exports.handler = async (event) => {
    const { key, bucket } = event; // You need to obtain the S3 key and bucket from your event.

    try {
        // 1. Fetch the image from S3.
        const s3Object = await s3.getObject({ Bucket: bucket, Key: key }).promise();

        // 2. Convert the image data to a readable stream.
        const imageStream = new PassThrough();
        imageStream.end(s3Object.Body);

        // 3. Create a FormData object and append the image data to it.
        const formData = new FormData();
        formData.append('photo', imageStream);

        // 4. Send the FormData to the external REST API.
        const response = await axios.post(upload_url, formData, {
            headers: {
                ...formData.getHeaders(),
                'Content-Type': `multipart/form-data; boundary=${formData.getBoundary()}`
            }
        });

        return response.data;
    } catch (error) {
        console.error('Error:', error);
        throw error;
    }
};

在这段代码中:
我们使用s3.getObject从S3获取图像。我们从S3对象的数据创建一个可读的流(imageStream)。我们创建一个FormData对象并将图像数据附加到它。我们使用Axios将请求中的FormData发送到外部REST API。请确保使此代码适应您的特定Lambda函数设置,确保您从事件或函数的输入中获得键和桶值。另外,将upload_url替换为外部REST API的实际URL。

相关问题