说我有这个HTML:
<img src="http://example.com/pic"/>
我想要做的是将example.com/pic映射到AWS API Gateway端点。
然后该端点将调用lambda函数。
lambda函数会读取s3存储桶中的随机图像并将其返回。
所以我的目标是使用STANDARD HTML图像标记,最后得到s3存储桶中的图像,但是通过lambda中的一些决策代码来决定要返回的图像。
我知道你可以使用s3直接提供静态内容(因此lambda可以决定什么图像)。我也知道我可以在lambda中做一些事情,比如b64编码响应,然后在客户端处理它,但我的目标是使用标准的HTML IMG标记。
这可能吗?
我已经尝试将ResponseStreamHandler(Java SDK)用于lambda并返回图像的字节数组,并且还添加了API网关配置以不将输出映射到JSON,但似乎没有任何效果!
答案 0 :(得分:19)
似乎AWS已经简化了这个过程,因此很多答案都已过时和/或过于复杂。
这是我通过API网关让Lambda返回图像的方式,截至2018年6月:
1)在API网关中,为您的API启用Use Lambda Proxy integration
。 (此设置位于“集成请求”部分,您已将类型设置为Lambda。)
2)在API网关中,选择您的API并单击Settings
。在Binary Media Types
添加*/*
。 (注意:我尝试添加'image / jpeg',但似乎需要*/*
才能使所有这些工作正常工作)
3)请务必部署您的API,否则您的更改将不会生效。 (在API网关中,选择您的API,然后选择操作&gt;部署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
设置为*/*
,如果您的Lambda正在返回,API网关仍会返回文本。
答案 1 :(得分:7)
幸运的是,现在AWS API Gateway支持二进制数据,但您还需要通过CLI更新资源方法,因为它尚未在控制台中实现。这是你需要做的:
Content-Type
设置为image/jpeg
头Content-Type
设置为'image/jpeg'
。 注意引用! contentHandling
属性设置为CONVERT_TO_BINARY
在这个伟大的分步指南中检查整个过程:https://stackoverflow.com/a/41434295/720665
答案 2 :(得分:5)
我遇到了类似的问题。如上所述,您目前无法直接从API网关端点返回二进制格式的图像,这是浏览器正确显示它所必需的。
但是,我解决了这个问题,而是让API网关返回 302重定向,指向S3中的正确文件。您可以让Lambda函数将url返回到该文件,该文件稍后将映射到API网关中的Location标头。浏览器将遵循重定向并正确显示图像。
有几种方法可以实现重定向,但我的确如下:
Lambda返回一个包含目标图像的对象,如下所示:
function handler(event, context) {
context.succeed({
location: "https://[bucket-name].s3-eu-west-1.amazonaws.com/myimage.png" });
});
}
从API网关中的集成响应中删除正常的“200”方法响应状态。将其替换为“302”响应状态,并添加映射到值“integration.response.body.location”的“位置”标题
将302状态添加到方法响应中
答案 3 :(得分:2)
为了清楚起见,客户端做了两个不同的请求:
换句话说,HTML中没有内嵌图像数据。
根据这些知识,您可以按照建议使用Lambda(在API网关后面)。 Lambda实现可以具有一些逻辑,用于确定存储在S3中的图像的URL。但是,Lambda返回JSON数据而不是HTML(有return the html in a variable之类的解决方法)会使事情变得棘手,特别是对于大型HTML页面。
我建议采用略有不同的方法,因为只是接收图像标签不会让你走得太远。我假设您可能会使用JavaScript内联HTML文档中的图像标记。然后,您可以让API Gateway / Lambda请求返回带有图像URL的JSON文档,并让JavaScript使用新URL更新现有图像标记或为您生成标记。
答案 4 :(得分:0)
目前无法实现,因为您无法通过AWS API网关返回二进制数据。
为此,lambda函数需要将图像数据作为二进制blob和一些元信息(如图像内容类型)返回。然后,AWS API Gateway需要能够将其映射到HTTP响应。例如: -
lambda返回:
{
contentType: 'image/png',
image: "encoded binary data"
}
然后API网关需要将contentType映射到&#39;内容类型&#39;响应的标题,并使用正确的编码和长度将图像数据放在响应的主体中。
不幸的是,它现在没有做到这一点。它只映射像application / json或application / xml这样的文本编码作为响应类型(毕竟它是为API设计的)。
您可以使用ElasticBeanstalk轻松实现此目的,您可以对http响应进行更多控制。