AWS API Gateway和Lambda返回图像

use*_*191 11 java api amazon-web-services aws-lambda aws-api-gateway

说我有这个HTML:

<img src="http://example.com/pic"/>
Run Code Online (Sandbox Code Playgroud)

我想做的是将example.com/pic映射到AWS API Gateway端点.

然后该端点将调用lambda函数.

该lambda函数将从s3存储桶中读取随机图像并将其返回.

因此,我的目标是使用标准HTML图像标记,最后得到s3存储桶中的图像,但是通过lambda中的一些决策代码来决定要返回的图像.

我知道你可以使用s3直接提供静态内容(因此lambda可以决定什么图像).我也知道我可以在lambda中做一些事情,比如b64编码响应,然后在客户端处理它,但我的目标是使用标准的HTML IMG标记.

这可能吗?

我已经尝试将ResponseStreamHandler(Java SDK)用于lambda并返回图像的字节数组,并且还添加了API网关配置以不将输出映射到JSON,但似乎没有任何效果!

Dou*_*g S 22

似乎AWS已经简化了这个过程,因此许多答案已经过时和/或过于复杂.

这是我在2018年6月通过API网关让Lambda返回图像的方式:

1)在API网关中,Use Lambda Proxy integration为您的API 启用.(此设置位于"集成请求"部分,您已将类型设置为Lambda.)

2)在API网关中,选择您的API并单击Settings.在Binary Media Types添加*/*.(注意:我尝试添加简单的'image/jpeg',但似乎需要*/*让所有这些工作)

3)请务必部署您的API,否则您的更改将不会生效.(在API Gateway中,选择您的API,然后选择Actions> Deploy 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
    };
Run Code Online (Sandbox Code Playgroud)

完成.

如果您将API设置为不需要身份验证,只需在浏览器中输入API链接,它就会显示图片.或者将API链接放入IMG标记中.例如<img src="https://asdf.execute-api.us-east-1.amazonaws.com/live/myapi" />

注意:即使在步骤2中设置了Binary Media Typesto */*,API Gateway仍会返回文本,如果这是Lambda返回的内容.

  • 通过在响应对象中包含 `isBase64Encoded` 作为 `true` 似乎发生了神奇的事情。这就是返回二进制数据的技巧。 (6认同)
  • 它需要 `*/*` 的原因是因为 APIG 愚蠢地要求接受头匹配。所以客户端 ** 必须** 发送 `Accept: image/jpeg` 以便进行二进制解码。由于 chrome(所有浏览器?)发送 `Accept: */*`,这使它工作。 (3认同)
  • 非常感谢你.我失去了这一步.3)请务必部署您的API,否则您的更改将不会生效.(在API Gateway中,选择您的API,然后选择Actions> Deploy API). (2认同)
  • 感谢您的* / *和每次更改内容时必须部署api的信息! (2认同)

Dav*_*mon 7

幸运的是,现在AWS API Gateway支持二进制数据,但您还需要通过CLI更新资源方法,因为它尚未在控制台中实现.这是你需要做的:

  1. 方法的方法响应
    设置Content-Typeimage/jpeg在HTTP 200状态响应标头中
  2. 在方法的Integration Response
    设置Content-Type'image/jpeg'Header Mappings.记住报价!
  3. 使用AWS CLI,在您的Integration Response上设置contentHandling属性CONVERT_TO_BINARY

在这个伟大的分步指南中检查整个过程:https: //stackoverflow.com/a/41434295/720665


The*_*dor 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" });
         });
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • 从API网关中的集成响应中删除正常的"200"方法响应状态.将其替换为"302"响应状态,并添加映射到值"integration.response.body.location"的"Location"标头

  • 将302状态添加到方法响应中


mat*_*sev 1

需要明确的是,客户端会发出两个不同的请求:

  1. 第一个获取 HTML(包括图像 url)。
  2. 第二个从 url 获取图像数据。

换句话说,图像数据没有内联在 HTML 中。

基于这些知识,您可以按照您的建议拥有 Lambda(位于 API 网关后面)。Lambda 实现可以具有一些逻辑来确定存储在 S3 中的图像的 url。然而,Lambda 返回 JSON 数据而不是 HTML(有一些解决方法,例如在变量中返回 html),这使得事情变得更加棘手,尤其是对于大型 HTML 页面。

我建议采用稍微不同的方法,因为仅接收图像标签不会让您走得太远。我假设您可能会使用 JavaScript 将图像标签内联到 HTML 文档中。然后,您不妨让 API Gateway / Lambda 请求返回带有图像 url 的 JSON 文档,并让 JavaScript 使用新 url 更新现有图像标签或为您生成标签。