AWS API Gateway和Lambda返回图像

时间:2016-03-04 19:01:56

标签: java api amazon-web-services aws-lambda aws-api-gateway

说我有这个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,但似乎没有任何效果!

5 个答案:

答案 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更新资源方法,因为它尚未在控制台中实现。这是你需要做的:

  1. 在您方法的方法响应中 在HTTP 200状态响应中将Content-Type设置为image/jpeg
  2. 在您方法的集成响应中 在标头映射中将Content-Type设置为'image/jpeg'注意引用!
  3. 使用AWS CLI,在集成响应中将contentHandling属性设置为CONVERT_TO_BINARY
  4. 在这个伟大的分步指南中检查整个过程: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)

为了清楚起见,客户端做了两个不同的请求:

  1. 第一个获取HTML(包括图片网址)。
  2. 第二个从网址获取图片数据。
  3. 换句话说,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响应进行更多控制。