【问题标题】:AWS API Gateway base64Decode produces garbled binary?AWS API Gateway base64Decode 产生乱码二进制文件?
【发布时间】:2017-05-16 17:18:38
【问题描述】:

我正在尝试从 AWS API Gateway 方法返回一个 1px 的 gif。

由于现在支持二进制数据,我使用以下“集成响应”映射返回图像/gif:

$util.base64Decode("R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7")

但是,当我在 Chrome 中查看此内容时,我看到返回以下二进制文件:

代替:

谁能帮我理解为什么这是乱码和错误的长度?或者我能做些什么来返回正确的二进制文件?在不使用 base64Decode 函数的情况下,我可以随时返回这个 1px 的 gif 吗?

非常感谢,这让我很痛苦!

编辑

这个人变得陌生了。看起来问题不在于 base64Decode,而在于二进制的一般处理。我在this blog post 和这个Stack Overflow question 之后添加了一个 Lambda 后端(以前我使用的是 Firehose)。我根据 documentation page 将图像设置为 binaryMediaType。

这让我可以通过网关 API 从 Lambda 传递以下图像/bmp 像素,并且它可以正常工作:

exports.handler = function(event, context) {

  var imageHex = "\x42\x4d\x3c\x00\x00\x00\x00\x00\x00\x00\x36\x00\x00\x00\x28\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x18\x00\x00\x00\x00\x00\x06\x00\x00\x00\x27\x00\x00\x00\x27\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\x00\x00";
  context.done(null, { "body":imageHex });

};

但是,以下表示 image/png 或 image/gif 的图像在通过时会出现乱码:

exports.handler = function(event, context) {

//var imageHex = "\x47\x49\x46\x38\x39\x61\x01\x00\x01\x00\x80\x00\x00\x00\x00\x00\xff\xff\xff\x21\xf9\x04\x01\x00\x00\x00\x00\x2c\x00\x00\x00\x00\x01\x00\x01\x00\x00\x02\x01\x44\x00\x3b";
//var imageHex = "\x47\x49\x46\x38\x39\x61\x01\x00\x01\x00\x80\x00\x00\xff\xff\xff\x00\x00\x00\x21\xf9\x04\x01\x00\x00\x00\x00\x2c\x00\x00\x00\x00\x01\x00\x01\x00\x00\x02\x02\x44\x01\x00\x3b";
  var imageHex = "\x47\x49\x46\x38\x39\x61\x01\x00\x01\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x21\xf9\x04\x01\x00\x00\x00\x00\x2c\x00\x00\x00\x00\x01\x00\x01\x00\x00\x02\x02\x44\x01\x00\x3b\x0a"
  context.done(null, { "body":imageHex });

};

这似乎与another Stack Overflow question 是同一个问题,但我希望通过 Gateway API 二进制支持来解决这个问题。不幸的是 image/bmp 不适用于我的用例,因为它不能是透明的......

如果它对任何人有帮助,请this has been a good tool 在 base64 和十六进制之间进行转换。

【问题讨论】:

  • Chrome 中的响应标头是什么样的?
  • 谢谢,响应头是:HTTP/1.1 200 OK Content-Type: image/gif Content-Length: 52 Connection: keep-alive Date: Mon, 02 Jan 2017 22:08:55 GMT x-amzn-RequestId: 0d3f620c-d138-11e6-941a-0f16afc9bdc4 X-Amzn-Trace-Id: Root=1-586acf77-93ce6c87faa62ee76758abf5 X-Cache: Miss from cloudfront Via: 1.1 227087338674ca3d3d23a79539f2998b.cloudfront.net (CloudFront) X-Amz-Cf-Id: 9V1XUr1cPqjm7Bj2HOFfakLlFM5MWo_Ucuv9cdk35xsBz_xhcPvixQ== 响应返回为:data:image/gif;base64,R0lGODlhAQABAO+/vQAAAAAA77+977+977+9Ie+/vQQBAAAAACwAAAAAAQABAAACAUQAOw==
  • 您的 API 网关的后端是什么?是 Lambda 吗?

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


【解决方案1】:

这似乎是以前的一个已知问题: https://forums.aws.amazon.com/thread.jspa?messageID=668306&#668306

但是现在他们已经添加了对二进制数据的支持应该是可能的: http://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-payload-encodings.html

看起来这是我们需要的位:“将 IntegrationResponse 资源的 contentHandling 属性设置为 CONVERT_TO_BINARY 以将响应负载从 Base64 编码的字符串转换为其二进制 blob”。那么我们就不需要base64Decode() 函数了。

现在进行测试,看看这是否有效。

编辑:我终于可以让它工作了。你可以在这里看到二进制图像: https://chtskiuz10.execute-api.us-east-1.amazonaws.com/prod/rest/image

这是我的 Lambda 函数,它将 base64 编码的 PNG 作为字符串返回: https://gist.github.com/davemaple/73ce3c2c69d5310331395a0210069263

我更新了方法响应如下:

我更新了集成响应以包含一个硬编码的图像/PNG 标头:

最后一步很棘手:将contentHandling 属性设置为“CONVERT_TO_BINARY”。我无法弄清楚如何在 AWS 控制台中进行操作。我必须使用 CLI API 来完成此操作:

aws apigateway update-integration-response \
    --profile davemaple \
    --rest-api-id chtskiuzxx \
    --resource-id ki1lxx \
    --http-method GET \
    --status-code 200 \
    --patch-operations '[{"op" : "replace", "path" : "/contentHandling", "value" : "CONVERT_TO_BINARY"}]'

我希望这会有所帮助。

【讨论】:

  • 感谢您的帮助戴夫,我在上面添加了我的调查的更多细节。真的很想听听你的进展!
  • 一旦您有机会进行审核,请告诉我您是否完成了这项工作。
  • 哇,成功了!我不能感谢你。我不会发现的!
  • 实际上这对我有用。因此,CLI 命令基本上是为了解决这样一个事实,即当您从“创建方法”屏幕中选择 Lambda 函数时,您无法设置“内容处理”下拉菜单。下拉菜单仅在您选择 AWS 服务时出现。
  • 我想在集成响应中将 contentHandling 属性添加到“CONVERT_TO_BINARY”,但在 aws Web 控制台中找不到任何方法。任何人这样做或任何其他解决方法,请告诉。
【解决方案2】:

查看this answer。它帮助我通过 GET 请求公开 PDF 文件以供下载,而无需任何额外的标题。

【讨论】:

    【解决方案3】:

    致其他有此问题的人:我还试图通过 API Gateway proxy integrationlambda 检索二进制图像,但后来我注意到它在 Lambda 控制台的二进制支持部分中显示:

    API Gateway 将查看 Content-TypeAccept HTTP 标头来决定如何处理正文。

    所以我在请求标头中添加了Accept: image/png,它起作用了。哦,快乐,快乐! 无需手动将内容处理更改为 CONVERT_TO_BINARY 或使用 cli。当然这排除了使用,例如,<img src= 直接(不能设置标题)。

    因此,为了通过代理集成从 lambda 通过 API 网关获取二进制文件:

    • 在 lambda 控制台(和部署)中列出所有支持的二进制内容类型
    • 请求 Accept 标头必须包含从 lambda 表达式返回的 Content-Type 标头
    • 返回的正文必须是 base64 编码的
    • 结果对象还必须将isBase64Encoded 属性设置为true

    代码:

    callback(null, {
        statusCode: 200,
        headers: { 'Content-Type': 'image/png' },
        body: buffer.toString('base64'),
        isBase64Encoded: true
    }
    

    【讨论】:

    • 这对我有用。此外,您可以将 Binary Media Types(在 API 的设置中)设置为 */*,然后您不需要设置 Accept 标头。但是需要注意的是,这会阻止您使用文本输出。
    • 此响应对象返回 500 内部服务器错误响应
    猜你喜欢
    • 2019-06-19
    • 1970-01-01
    • 2021-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-08
    • 2017-06-30
    • 1970-01-01
    相关资源
    最近更新 更多