在 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的主要内容,如果未能解决你的问题,请参考以下文章