java AWS API网关和Lambda返回图像

ryhaxcpt  于 2022-12-25  发布在  Java
关注(0)|答案(6)|浏览(152)

假设我有这个HTML:

<img src="http://example.com/pic"/>

What I would like to do is have example.com/pic map to an AWS API Gateway endpoint.
然后,该端点将调用lambda函数。
lambda函数将从s3桶中读取一个随机图像并返回。
所以我的目标是使用一个STANDARD HTML图像标记,并最终得到一个来自s3桶的图像,但要通过lambda中的一些决策代码来决定要返回的图像。
我知道你可以直接使用s3来提供静态内容(因此使用lambda来决定使用什么图像),我也知道我可以在lambda中做一些事情,比如b64编码响应,然后在客户端处理它,但是我的目标是使用标准的HTML IMG标记。
这可能吗?
我试过使用ResponseStreamHandler(Java SDK)来处理lambda并返回图像的字节数组,还添加了API网关配置以不将输出Map到JSON,但似乎什么都不起作用!

myss37ts

myss37ts1#

AWS似乎简化了这一过程,以至于许多答案都过时了和/或过于复杂。
这就是我如何让Lambda通过API Gateway返回图像的方法,截至2018年6月:
1)在API Gateway中,为您的API启用Use Lambda Proxy integration。(此设置位于集成请求部分,您已在此处将类型设置为Lambda。
2)在API网关中,选择您的API并单击Settings。在Binary Media Types中添加*/*。(注意:我试着简单地添加"image/jpeg",但似乎需要*/*才能使所有这些工作)
3)确保部署您的API,否则您的更改将不会生效。(在API网关中,选择您的API,然后选择操作〉部署API)。
4)在Lambda代码中,以Base64编码返回图像(此示例为C#代码):

// set the Content-type header
    // set to whichever image type you're returning
    var headersDic = new Dictionary<string, string>();
    headersDic.Add("Content-type", "image/jpeg");

    // return the response object that APIGateway requires
    return new APIGatewayProxyResponse
    {
        StatusCode = 200,
        Headers = headersDic,
        // return the image in Base64 encoding
        Body = Convert.ToBase64String(...your image data...),
        IsBase64Encoded = true
    };

好的。
如果您已经将API设置为不需要身份验证,只需在浏览器中输入API链接,它就会显示图像。或者将API链接放入IMG标签中。例如<img src="https://asdf.execute-api.us-east-1.amazonaws.com/live/myapi" />
注意:即使在步骤2中您将Binary Media Types设置为*/*,API Gateway仍然会返回文本(如果这是您的Lambda返回的内容)。

n3ipq98p

n3ipq98p2#

幸运的是,现在AWS API Gateway支持二进制数据,尽管您还需要通过CLI更新资源方法,因为它尚未在控制台中实现。
1.在方法的方法响应
在HTTP 200状态响应标头中将Content-Type设置为image/jpeg
1.在方法的积分响应
在标题Map中将Content-Type设置为'image/jpeg'注意引号!
1.使用AWS CLI,在集成响应中将contentHandling属性设置为CONVERT_TO_BINARY
在这个伟大的分步指南中检查整个过程:https://stackoverflow.com/a/41434295/720665

kzipqqlq

kzipqqlq3#

我也遇到过类似的问题,如前所述,目前你不能直接从API网关端点返回二进制格式的图像,而这是浏览器正确显示图像所必需的。
然而,我通过让API Gateway返回一个302 Redirect,指向S3中正确的文件来解决这个问题。您可以让Lambda函数返回文件的url,稍后将其Map到API Gateway中的Location头。浏览器将遵循重定向并正确显示图像。
有几种方法可以实现重定向,但我做了如下:

  • Lambda返回一个带有目标图像的对象,如下所示:
function handler(event, context) {
     context.succeed({ 
         location: "https://[bucket-name].s3-eu-west-1.amazonaws.com/myimage.png" });
     });
}
  • 从API网关中的集成响应中删除正常的“200”方法响应状态。将其替换为“302”响应状态,并添加Map到值“integration.response.body.location”的“Location”标头
  • 将302状态也添加到方法响应中
krcsximq

krcsximq4#

需要说明的是,客户端执行两个不同的请求:
1.第一个获取HTML(包括图像url)的。
1.第二个从url中提取图像数据。
换句话说,图像数据未内联在HTML中。
基于这些知识,您可以按照建议使用Lambda(位于API网关之后)。Lambda实现可以包含一些逻辑,用于确定存储在S3中的图像的url。但是,Lambda返回JSON数据而不是HTML(存在return the html in a variable等解决方案),这使得事情变得更加棘手,特别是对于大型HTML页面。
我建议一个稍微不同的方法,因为仅仅接收一个图像标签不会让你走得很远。我假设你会在一个HTML文档中内联图像标签,可能是通过使用JavaScript。然后你也可以让API Gateway / Lambda请求返回一个带有图像url的JSON文档,让JavaScript用新的url更新现有的图像标签,或者为你生成标签。

shyt4zoc

shyt4zoc5#

目前还不可能,因为您无法通过AWS API Gateway返回二进制数据。
要实现这一点,lambda函数需要以二进制blob的形式返回图像数据,以及一些元信息,如图像内容类型。然后,AWS API Gateway需要能够将其Map到HTTP响应。例如:-
lambda返回:第一个月
则API网关需要将contentTypeMap到响应的“content-type”报头,并将图像数据以正确的编码和长度放入响应的主体中。
不幸的是,它现在还不能这样做,它只将application/json或application/xml这样的文本编码Map为响应类型(毕竟它是为API设计的)。
使用ElasticBeanstalk可以非常容易地实现这一点,在这里您可以对http响应进行更多的控制。

ccgok5k5

ccgok5k56#

我在重新考虑我的设计时解决了这个问题。潜在的想法是Lambda是好的计算单元和坏的文件服务器。
我变了

  • 第一个月

变成

  • Client > APIGW > Lambda > SignedURL
  • 那么Client(SignedURL) > Image

由于我的客户端是基于Web的,因此在这种转变之后,一切都变得更容易了

相关问题