将图像从 S3 存储桶下载到 Lambda 临时文件夹 (Node.js)

Posted

技术标签:

【中文标题】将图像从 S3 存储桶下载到 Lambda 临时文件夹 (Node.js)【英文标题】:Download image from S3 bucket to Lambda temp folder (Node.js) 【发布时间】:2016-12-22 16:49:37 【问题描述】:

大家好。

我有一个简单的问题:如何将图像从 S3 存储桶下载到 Lambda 函数临时文件夹进行处理?基本上,我需要将它附加到电子邮件中(我可以在本地测试时这样做)。

我试过了:

s3.download_file(bucket, key, '/tmp/image.png')

以及(不确定哪些参数可以帮助我完成工作):

s3.getObject(params, (err, data) => 
    if (err) 
        console.log(err);
        const message = `Error getting object $key from bucket $bucket.`;
        console.log(message);
        callback(message);
     else 

        console.log('CONTENT TYPE:', data.ContentType);
        callback(null, data.ContentType);
    
);

就像我说的,一个简单的问题,由于某种原因我找不到解决方案。

谢谢!

【问题讨论】:

【参考方案1】:

您可以使用 aws s3 api 获取图像,然后使用 fs 将其写入 tmp 文件夹。

var params =    Bucket: "BUCKET_NAME",   Key: "OBJECT_KEY" ;  

s3.getObject(params, function(err, data)   if (err) 
    console.error(err.code, "-", err.message);
    return callback(err);   

  fs.writeFile('/tmp/filename', data.Body, function(err)
    if(err)
      console.log(err.code, "-", err.message);

    return callback(err);   
  ); 
);

出于好奇,您为什么需要编写文件才能附加它?将文件写入磁盘似乎有点多余,以便您可以从磁盘读取它

【讨论】:

我正在使用 SendGrid,因此似乎必须将文件存在于本地磁盘上才能附加它。你是说这不是必须的吗? 我对 SendGrid 一点也不熟悉,所以我不确定,但我的想法是你会将它下载到内存中,我认为这可能是一个问题,具体取决于文件大小。 @JonathanSeed 我实际上遇到了这个问题,我正在使用getObject 读取一个 150-200mb 的文本文件,这使我的 Lambda 函数达到其最大内存限制。是否有解决方法或为什么内存限制如此之低? @V.Samma 您可以在控制台的“高级设置”下为 lambda 函数配置内存。我相信默认值为 128 mb。 @JonathanSeed 我可能还不够清楚。通过达到其最大内存限制,我的意思是我已经为我的 lambda 函数设置了最大内存,即 1536MB,当我的 lambda 函数尝试读取 2 个文件(一个是几 KB-s,一个是 150- 200MB-s),然后将它们连接为字符串值并将结果写回 S3。【参考方案2】:

如果您直接将其写入文件系统,您也可以do it with streams。它可能会更快/对内存更友好,尤其是在 Lambda 等内存受限的环境中。

var fs = require('fs');
var path = require('path');

var params = 
    Bucket: "mybucket",
    Key: "image.png"
;

var tempFileName = path.join('/tmp', 'downloadedimage.png');
var tempFile = fs.createWriteStream(tempFileName);

s3.getObject(params).createReadStream().pipe(tempFile);

【讨论】:

您知道createReadStream() 是否让aws-sdk 触发多个 GET 调用,或者它只执行一个然后流式传输数据?我担心这个解决方案的成本 这是什么路径? @Sinn 我相信它应该只触发一个 GET 调用。它和普通的 getObject 做同样的事情,但只是暴露了底层流 @VikasSatpute 我编辑添加路径,感谢您指出【参考方案3】:
// Using NodeJS version 10.0 or later and promises

const fsPromise = require('fs').promises;

try 
    const params = 
        Bucket: 's3Bucket',
        Key: 'file.txt',
    ;

    const data = await s3.getObject(params).promise();

    await fsPromise.writeFile('/tmp/file.txt', data.Body);

 catch(err) 
    console.log(err);

【讨论】:

请在您的回答中添加一些细节

以上是关于将图像从 S3 存储桶下载到 Lambda 临时文件夹 (Node.js)的主要内容,如果未能解决你的问题,请参考以下文章

AWS Lambda使用S3

AWS Lambda 返回权限被拒绝尝试从 S3 存储桶获取对象

将图像从 opencv 上传到 s3 存储桶

从 s3 存储桶获取 2 个文件,并在使用 lambda 节点 js 将其上传到 s3 存储桶后制作 1 个 zip 文件

从 node.js 将图像上传到 s3 存储桶

使用带有 Node.js 的 AWS Lambda 函数从 S3 存储桶中提取 zip 文件并上传到另一个存储桶