java AWS API Gateway 和 Lambda 返回图像
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/35804042/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
AWS API Gateway and Lambda to return image
提问by user1736191
Say I have this HTML:
假设我有这个 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.
我想做的是将 example.com/pic 映射到 AWS API Gateway 端点。
That endpoint would then call a lambda function.
然后该端点将调用 lambda 函数。
That lambda function would read a random image from an s3 bucket and return it.
该 lambda 函数将从 s3 存储桶中读取随机图像并返回它。
So my aim is to use a STANDARD HTML image tag and end up with an image from an s3 bucket but going via some decision code in the lambda to decide the image to return.
所以我的目标是使用 STANDARD HTML 图像标签并最终得到来自 s3 存储桶的图像,但通过 lambda 中的一些决策代码来决定要返回的图像。
I know you can use s3 to serve static content directly (hence the lambda to make the decision about what image). I also know I could do stuff in the lambda like b64 encode the response and then handle it on the client but I am aiming to use the standard HTML IMG tag.
我知道你可以使用 s3 直接提供静态内容(因此 lambda 来决定什么图像)。我也知道我可以在 lambda 中做一些事情,比如 b64 对响应进行编码,然后在客户端上处理它,但我的目标是使用标准的 HTML IMG 标签。
Is this possible?
这可能吗?
I've tried using the ResponseStreamHandler (Java SDK) for the lambda and returning the byte array of the image and also added the API gateway config to not map the output to JSON, but nothing seems to work!
我已经尝试将 ResponseStreamHandler (Java SDK) 用于 lambda 并返回图像的字节数组,并且还添加了 API 网关配置以不将输出映射到 JSON,但似乎没有任何效果!
回答by Doug S
It seems AWS has simplified this process, so that many answers are outdated and/or overly complicated.
AWS 似乎简化了这个过程,因此许多答案已经过时和/或过于复杂。
This is how I got Lambda to return an image through the API Gateway, as of June 2018:
这是我让 Lambda 通过 API 网关返回图像的方式,截至 2018 年 6 月:
1) In API Gateway, enable Use Lambda Proxy integration
for your API. (This setting is located on the Integration Request section, where you had set the type to Lambda.)
1) 在 API Gateway 中,Use Lambda Proxy integration
为您的 API启用。(此设置位于集成请求部分,您已在其中将类型设置为 Lambda。)
2) In API Gateway, select your API and click Settings
. In Binary Media Types
add */*
. (Note: I tried adding simply 'image/jpeg', but it seems to require */*
to get all of this to work)
2) 在 API Gateway 中,选择您的 API 并单击Settings
。在Binary Media Types
添加*/*
. (注意:我尝试简单地添加“图像/jpeg”,但似乎需要*/*
让所有这些工作)
3) Be sure to deploy your API, otherwise your changes will not be live. (In API Gateway, select your API, then Actions > Deploy API).
3) 请务必部署您的 API,否则您的更改将不会生效。(在 API Gateway 中,选择您的 API,然后选择操作 > 部署 API)。
4) In your Lambda code, return your image in Base64 encoding (this example is C# code):
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
};
Done.
完毕。
If you've setup your API to not require authentication, simply type your API link into your browser, and it will display the image. Or put the API link into an IMG
tag. e.g. <img src="https://asdf.execute-api.us-east-1.amazonaws.com/live/myapi" />
如果您已将 API 设置为不需要身份验证,只需在浏览器中输入您的 API 链接,它就会显示图像。或者将 API 链接放入IMG
标签中。例如<img src="https://asdf.execute-api.us-east-1.amazonaws.com/live/myapi" />
Note: Even though in step 2 you set the Binary Media Types
to */*
, API Gateway will still return text if that is what your Lambda is returning.
注意:即使在第 2 步中您将 设置Binary Media Types
为*/*
,如果您的 Lambda 返回的是文本,API Gateway 仍将返回文本。
回答by David Salamon
Luckily, now AWS API Gateway supports binary data, though you also need to update your resource method through the CLI as it is not yet implemented in the Console. This is what you need to do:
幸运的是,现在 AWS API Gateway 支持二进制数据,但您还需要通过 CLI 更新您的资源方法,因为它还没有在控制台中实现。这是你需要做的:
- In the Method Responseof your method
SetContent-Type
asimage/jpeg
in HTTP 200 Status Response Header - In the Integration Responseof your method
SetContent-Type
as'image/jpeg'
in Header Mappings. Mind the quotes! - With the AWS CLI, set
contentHandling
attribute toCONVERT_TO_BINARY
on your Integration Response
- 在您的方法的方法响应中
设置Content-Type
为image/jpeg
HTTP 200 状态响应头 - 在您的方法的集成响应中
设置Content-Type
为'image/jpeg'
标题映射。注意引号! - 使用 AWS CLI,在集成响应中将
contentHandling
属性设置为CONVERT_TO_BINARY
Check to entire process in this great step-by step guide: https://stackoverflow.com/a/41434295/720665
在这个伟大的分步指南中检查整个过程:https: //stackoverflow.com/a/41434295/720665
回答by Theodor
I've run in to a similar problem. As mentioned you currently can't directly return your image in binary format from your API Gateway endpoint, which would be required for the browser to display it correctly.
我遇到了类似的问题。如前所述,您目前无法直接从 API 网关端点以二进制格式返回图像,这是浏览器正确显示图像所必需的。
However, I solved this by instead having API Gateway return a 302 Redirect, pointing to the correct file in S3. You can have your Lambda function return the url to the file, which is later on mapped to the Location header in API Gateway. The browser will follow the redirect and display the image properly.
但是,我通过让 API Gateway 返回302 Redirect来解决这个问题,指向 S3 中的正确文件。您可以让 Lambda 函数将 url 返回到文件,该文件稍后会映射到 API Gateway 中的 Location 标头。浏览器将遵循重定向并正确显示图像。
There are several ways to implement the redirect, but I did as follow:
有几种方法可以实现重定向,但我是这样做的:
Lambda returns an object with the target image like so:
function handler(event, context) { context.succeed({ location: "https://[bucket-name].s3-eu-west-1.amazonaws.com/myimage.png" }); }); }
Remove the normal '200' Method Response Status from The Integration Response in API Gateway. Replace it with a '302' response status and add the 'Location' header mapped to value 'integration.response.body.location'
Add the 302 status to the Method Response as well
Lambda 返回一个带有目标图像的对象,如下所示:
function handler(event, context) { context.succeed({ location: "https://[bucket-name].s3-eu-west-1.amazonaws.com/myimage.png" }); }); }
从 API Gateway 中的集成响应中删除正常的“200”方法响应状态。将其替换为“302”响应状态并添加映射到值“integration.response.body.location”的“Location”标头
也将 302 状态添加到方法响应中
回答by matsev
Just to be clear, the client does two different requests:
需要明确的是,客户端执行两个不同的请求:
- The first to get the HTML (including the image url).
- The second to fetch the image data from the url.
- 第一个获取 HTML(包括图像 url)。
- 第二个从 url 获取图像数据。
In other words, the image data is not inlined in the HTML.
换句话说,图像数据没有内联在 HTML 中。
Based on this knowledge you can have a Lambda (behind the API gateway) as you suggest. The Lambda implementation can have some logic that determines the url to the image stored in S3. However, the Lambda returns JSON data and not HTML (there are workarounds such as return the html in a variable) which makes things trickier, especially for large HTML pages.
根据这些知识,您可以按照您的建议使用 Lambda(在 API 网关后面)。Lambda 实现可以有一些逻辑来确定存储在 S3 中的图像的 url。但是,Lambda 返回 JSON 数据而不是 HTML(有一些变通方法,例如在变量中返回 html),这使事情变得更加棘手,尤其是对于大型 HTML 页面。
I suggest a slightly different approach, since just receiving an image tag will not get you far. I assume you will inline the image tag in a HTML document, probably by using JavaScript. Then you might as well let the API Gateway / Lambda request return a JSON document with the image url and let the JavaScript either update an existing image tag with the new url or generate the tag for you.
我建议采用稍微不同的方法,因为仅接收图像标签不会让您走得更远。我假设您将在 HTML 文档中内联图像标记,可能是使用 JavaScript。那么您不妨让 API Gateway / Lambda 请求返回一个带有图像 url 的 JSON 文档,并让 JavaScript 使用新的 url 更新现有的图像标签或为您生成标签。
回答by aomega
It currently isn't possible because you cannot return binary data through the AWS API Gateway.
目前无法实现,因为您无法通过 AWS API Gateway 返回二进制数据。
For this to work, the lambda function would need to return the image data as binary blob, and some meta-information such as the image content type. Then, AWS API Gateway would need to be able to map this to the HTTP response. For example:-
为此,lambda 函数需要将图像数据作为二进制 blob 返回,以及一些元信息,例如图像内容类型。然后,AWS API Gateway 需要能够将其映射到 HTTP 响应。例如:-
lambda returns:
{
contentType: 'image/png',
image: "encoded binary data"
}
拉姆达返回:
{
contentType: 'image/png',
image: "encoded binary data"
}
then API gateway would need to map contentType to the 'content-type' header of the response, and put the image data in the body of the response with the right encoding and length.
然后 API 网关需要将 contentType 映射到响应的“content-type”标头,并将图像数据以正确的编码和长度放入响应正文中。
Unfortunately, it doesn't do this right now. It only maps text encodings like application/json or application/xml as the response type (it is designed for APIs after all).
不幸的是,它现在不这样做。它只将诸如 application/json 或 application/xml 之类的文本编码映射为响应类型(毕竟它是为 API 设计的)。
You could very easily achieve this using ElasticBeanstalk where you have a lot more control over the http response.
您可以使用 ElasticBeanstalk 轻松实现这一点,您可以在其中更好地控制 http 响应。