繁体   English   中英

如何在Python中返回AWS中lambda function的二进制数据?

[英]How to return binary data from lambda function in AWS in Python?

我无法通过 python lambda 返回二进制数据。 缩略图的节点模板工作正常,但我无法让 python lambda 工作。 下面是我的 lambda 中的相关行。 print("image_data " + image_64_encode)行将 base64 编码图像打印到日志中。

def lambda_handler(event, context):
    img_base64 = event.get('base64Image')
    if img_base64 is None:
        return respond(True, "No base64Image key")

    img = base64.decodestring(img_base64)
    name = uuid.uuid4()
    path = '/tmp/{}.png'.format(name)

    print("path " + path)

    image_result = open(path, 'wb')
    image_result.write(img)
    image_result.close()

    process_image(path)

    image_processed_path = '/tmp/{}-processed.png'.format(name)
    print("image_processed_path " + image_processed_path)
    image_processed = open(image_processed_path, 'rb')
    image_processed_data = image_processed.read()
    image_processed.close()
    image_64_encode = base64.encodestring(image_processed_data)

    print("image_data " + image_64_encode)


    return respond(False, image_64_encode)


def respond(err, res):
    return {
        'statusCode': '400' if err else '200',
        'body': res,
        'headers': {
            'Content-Type': 'image/png',
        },
        'isBase64Encoded': 'true'
    }

任何指向我做错了什么的指示?

我终于想通了这一点。 从 python lambda 返回二进制数据是可行的。

按照此处的说明操作: https : //aws.amazon.com/blogs/compute/binary-support-for-api-integrations-with-amazon-api-gateway/

创建新方法时,请务必选中“使用 Lambda 代理集成”。

还要确保您的 Python Lambda 响应返回 base64 编码的正文,将isBase64Encoded设置为True和适当的内容类型:

import base64

def lambda_handler(event, context):
    # ...

    body = base64.b64encode(bin_data)

    return {'isBase64Encoded'   : True,
            'statusCode'        : 200,
            'headers'           : { 'Content-Type': content_type },
            'body'              : body }

那么:

对于您的每个路线/方法问题:

apigateway update-integration-response --rest-api-id <api-id> --resource-id <res-id> --http-method POST --status-code 200 --patch-operations "[{\"op\" : \"replace\", \"path\" : \"/contentHandling\", \"value\" : \"CONVERT_TO_BINARY\"}]"

在 AWS 控制台中。 可以在 API 网关的“面包屑”中看到,例如:

<api-id> = zdb7jsoey8
<res-id> = zy2b5g

然后:您需要“部署 API”。 根据我的发现,它仅在部署 API 后才有效。

确保在部署之前设置“二进制媒体类型”。

提示:这里不错的 AWS shell 终端: https : //github.com/awslabs/aws-shell

pip install aws-shell

遵循上述所有步骤对我的情况不起作用,因为对 content-type = */*的二进制支持会将所有响应转换为二进制。

我的情况:

  • 多个 lambda 函数返回 json(文本),只有一个 lambda 返回二进制文件。 所有都启用了lambda 代理

  • lambda 位于 API 网关中

  • API 网关位于 CloudFront 后面

提示:我注意到 API Gateway -> Settings 中有一个重要信息

二进制支持说明

引用:

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

这意味着Content-Type响应头必须匹配Accept请求头

解决方法:

  1. 将 API 网关中的二进制媒体类型设置为您的 MIME 类型:image/jpg

  2. 在您的 HTTP 请求中设置Accept: image/jpg

  3. 在您的 HTTP 响应中设置Content-Type: image/jpg

 { "isBase64Encoded": True, "statusCode": 200, "headers": { "content-type": "image/jpg"}, "body": base64.b64encode(content_bytes).decode("utf-8") }
  1. 接下来,我们必须告诉 CloudFront 接受来自请求的“Accept”标头。 因此,在 CloudFront 发行版中,单击您的 API 网关实例(ID 可单击),一旦重定向到 CloudFront 实例,请转到“行为”选项卡,选择您的 API 的路径模式(例如:/api/*)并单击“编辑”按钮。

路径模式示例

在新屏幕上,您必须将Accept标头添加到白名单。

白名单 接受

注意 1:如果您有多种文件类型,则必须在 API 网关设置中将它们全部添加到Binary Media Types

注 2:对于那些来自无服务器并希望在部署 lambdas 时设置二进制类型的人,请查看这篇文章: 为 API 网关设置二进制媒体类型

plugins:
  - serverless-apigw-binary

custom:
  apigwBinary:
    types:
- 'image/jpeg'

cloudfront 的 serverless.yml 文件应包含:

resources:
    WebAppCloudFrontDistribution:
      Type: AWS::CloudFront::Distribution
      Properties:
        DistributionConfig:
          ...
          CacheBehaviors:
            ...
            - 
              #API calls
              ...
              ForwardedValues:
                ...
                Headers:
                  - Authorization
                  - Accept

据我所知,Python 3 也是这种情况。我试图返回一个二进制数据(字节)。 它根本不起作用。

我也尝试使用 base-64 编码,但没有成功。

这是与 API 网关和代理集成。

[更新]

我终于意识到如何做到这一点。 启用了*/*类型的二进制支持,然后返回了这个:

return({
        "isBase64Encoded": True,
        "statusCode": 200,
        "headers": {
                "content-type": "image/jpg",
        },  
        'body':  base64.b64encode(open('image.jpg', 'rb').read()).decode('utf-8')
})  

大约 6 个月前,我遇到了同样的问题。 看起来虽然 API Gateway 现在有二进制支持(以及 JS 中的示例),但 Python 2.7 Lambda 仍然不支持有效的二进制响应,不确定 Python 3.6。

由于 JSON 包装,Base64 编码的响应存在问题。 我在客户端编写了一个自定义 JS,手动从这个 JSON 中取出 base-64 图像,但这也是一个糟糕的解决方案。

将结果上传到 S3(在 CloudFront 后面)并将 301 返回到 CloudFront 似乎是一个很好的解决方法。 最适合我。

我的问题有所不同 - 您需要在更改二进制媒体类型重新部署 Lambda。 这并不明显,我在没有任何效果的情况下更改二进制媒体类型,并且坚持了好几天。 参考.NET核心回复:

var response = new APIGatewayProxyResponse
{
    StatusCode = 200,
    Body = base64String,
    IsBase64Encoded = true,
    Headers = new Dictionary<string, string> {
        {"Content-Type", "application/pdf"} 
    }
};

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM