【问题标题】:AWS API Gateway and Lambda to return imageAWS API Gateway 和 Lambda 返回图像
【发布时间】:2018-06-04 03:42:07
【问题描述】:

假设我有这个 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 标记。

这可能吗?

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

【问题讨论】:

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


    【解决方案1】:

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

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

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

    2) 在 API Gateway 中,选择您的 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
        };
    

    完成。

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

    注意:即使在第 2 步中您将 Binary Media Types 设置为 */*,如果您的 Lambda 返回的是文本,API Gateway 仍将返回文本。

    【讨论】:

    • 非常感谢。我失去了这一步。 3) 确保部署您的 API,否则您的更改将无法生效。 (在 API Gateway 中,选择您的 API,然后选择 Actions > Deploy API)。
    • 它需要*/* 的原因是因为APIG 愚蠢地要求接受标头匹配。因此客户端必须发送Accept: image/jpeg 以便进行二进制解码。由于 chrome(所有浏览器?)发送Accept: */*,这使它工作。
    • 感谢*/* 以及每次更改时必须部署 api 的信息!
    • 在响应对象中包含isBase64Encoded 作为true 似乎发生了魔法。这就是返回二进制数据的诀窍。
    • @JochemSchulenklopper 所有这些都是返回图像所必需的。
    【解决方案2】:

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

    1. 在您方法的方法响应
      在 HTTP 200 状态响应中将 Content-Type 设置为 image/jpeg 页眉
    2. 在您方法的集成响应
      在标头映射中将Content-Type 设置为'image/jpeg'注意引号!
    3. 使用 AWS CLI,在您的集成响应中将 contentHandling 属性设置为 CONVERT_TO_BINARY

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

    【讨论】:

      【解决方案3】:

      我遇到了类似的问题。如前所述,您目前无法从 API Gateway 端点以二进制格式直接返回您的图像,浏览器需要这样才能正确显示它。

      但是,我通过让 API Gateway 返回 302 重定向 来解决这个问题,指向 S3 中的正确文件。您可以让 Lambda 函数将 url 返回到文件,该文件稍后会映射到 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”响应状态并添加映射到值“integration.response.body.location”的“Location”标头

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

      【讨论】:

        【解决方案4】:

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

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

        换句话说,图像数据没有内联在 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 更新现有的图片标签或为你生成标签。

        【讨论】:

          【解决方案5】:

          目前不可能,因为您无法通过 AWS API Gateway 返回二进制数据。

          为此,lambda 函数需要以二进制 blob 形式返回图像数据,以及一些元信息,例如图像内容类型。然后,AWS API Gateway 需要能够将其映射到 HTTP 响应。例如:-

          lambda 返回: { contentType: 'image/png', image: "encoded binary data" }

          然后 API 网关需要将 contentType 映射到响应的“content-type”标头,并将图像数据以正确的编码和长度放入响应的正文中。

          不幸的是,它现在不这样做。它仅将诸如 application/json 或 application/xml 之类的文本编码映射为响应类型(毕竟它是为 API 设计的)。

          您可以使用 ElasticBeanstalk 轻松实现此目的,您可以更好地控制 http 响应。

          【讨论】:

          猜你喜欢
          • 2017-04-19
          • 2015-10-15
          • 2018-02-14
          • 2018-11-28
          • 1970-01-01
          • 2017-09-07
          • 2021-03-30
          • 2017-08-24
          • 2020-03-23
          相关资源
          最近更新 更多