在 AWS Lambda 函数中从 S3 获取对象并发送到 Api Gateway

Posted

技术标签:

【中文标题】在 AWS Lambda 函数中从 S3 获取对象并发送到 Api Gateway【英文标题】:Get object from S3 in AWS Lambda function and send to Api Gateway 【发布时间】:2015-11-19 16:45:39 【问题描述】:

我正在尝试从存储桶中获取 .jpg 文件并将其发送回 api 网关。当我看到正在记录的内容时,我相信我的设置是正确的。它可以很好地从 s3 中获取文件,而 gm 是 graphicsmagick 库。不知道我是否正确使用它。

在 lambda 函数中我这样做(很多代码来自 aws 示例):

async.waterfall([
    function download(next) 
        console.log(srcKey);
        console.log(srcBucket);
        // Download the image from S3 into a buffer.
        s3.getObject(
                Bucket: srcBucket,
                Key: srcKey
            ,
            next);
        ,
    function transform(response, next) 
        console.log(response);
        next(null, 'image/jpeg', gm(response.Body).quality(85));

    ,

    function sendData(contentType, data, next)
        console.log(contentType);
        console.log(data);
        imageBuffer = data.sourceBuffer;
        context.succeed(imageBuffer);
    
    ]
);

响应头的内容长度为:85948,这似乎不正确,因为原始文件只有 36kb。有谁知道我做错了什么?

【问题讨论】:

图像可能会因处理而增大,这并非不可想象,但似乎不太可能。实际的响应正文是什么样的,例如,保存然后在文本/十六进制编辑器中查看? 哈基本上实现了完全相同的东西,只是在几个小时后终于偶然发现了这个问答:'( 现在有可能 - aws.amazon.com/blogs/compute/… 【参考方案1】:

您可以轻松实现 Get Image API Gateway Lambda S3 集成。

在 lambda 中,而不是 json,返回图像的 base64 字符串表示(buffer.toString('base64')),强制 API Gateway 将字符串转换为二进制并添加特定的Content-Type(因此您不需要使用它们有限的二进制支持强制您发送特定的 Accept 标头)。

在 AWS 控制台中,进入 API Gateway,然后进入相关方法并更新设置:

集成请求

取消选中:使用 Lambda 代理集成

方法响应

添加响应 -> HTTP 状态:200 添加标题:内容类型

集成响应 -> 标头映射 -> 响应标头 -> 内容类型

映射值:'image/jpeg'(单引号问题)

从命令行,运行以下命令强制将字符串转换为二进制。 首先,从 API Gateway 检索 rest-api-idresource-id。 然后,在 CLI 中运行(将 rest-api-id 和 resource-id 替换为您自己的):

aws apigateway put-integration-response --rest-api-id <rest-api-id> --resource-id <resource-id> --http-method GET --status-code 200 --content-handling CONVERT_TO_BINARY

【讨论】:

有没有办法通过 Lambda 代理集成来做到这一点?当我取消选中使用 Lambda 代理集成时,我的查询字符串不再传递给 Lambda 函数。【参考方案2】:

当您将API GatewayLambda 一起使用时,您不应使用API Gateway 来传回二进制内容。 API GatewayLambda 设置为响应 XML/JSON 数据。详细了解here 的原因和方式。

尝试更改您的回调链,以便将修改后的图像上传回S3。上传成功后,发回目标对象的URI,并将客户端重定向到它。

【讨论】:

我在文档中没有看到任何排除这一点的内容。你可以说得更详细点吗?服务的预期用途并不总是排除替代应用程序,并且 OP 的应用程序似乎是合法的。通过 API Gateway 返回二进制内容是否存在实际限制? 简单地说:context.done(...) 在你的缓冲区上调用.toString()AWS Gateway 数据管道围绕 Integration Request/Response 旋转,并且始终是 JSON/XML。 此外,通过 API 本身传递内容在 AWS 环境中是一种不好的做法。 API GatewayLambda 的超时时间都相对较短。 API Gateway 有 30 秒,Lambda 有 60 秒。 好的,感谢您的帮助。我会进一步研究它,但你所说的将修改后的图像存储回 s3 确实有道理。

以上是关于在 AWS Lambda 函数中从 S3 获取对象并发送到 Api Gateway的主要内容,如果未能解决你的问题,请参考以下文章

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

在不同账户的 Lambda 中从 AWS Athena 查询 S3 文件时访问被拒绝

AWS Lambda无法删除Amazon S3对象

如何使用 lambda 函数从 AWS s3 获取文本文件的内容?

在 aws lambda 中在 python 中从 ANSI 转换为 UTF-8

使用 boto3 lib 和 AWS Lambda 从 S3 存储桶中的压缩文件中获取数据流