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

问题描述

我无法让 python lambda 返回二进制数据.

引用:

<块引用>

API Gateway 将查看 Content-Type 和 Accept HTTP 标头来决定如何处理正文.

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

解决方案:

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

  2. 在你的 HTTP 请求集中 Accept: image/jpg

  3. 在你的 HTTP 响应集中 Content-Type: image/jpg

<块引用>

<代码>{isBase64Encoded":真,状态码":200,标题":{内容类型":图像/jpg"},正文":base64.b64encode(content_bytes).decode(utf-8")}

  1. 接下来,我们必须告诉 CloudFront 接受请求中的Accept"标头.因此,在 CloudFront 分发中,单击您的 API Gateway 实例(ID 可单击),一旦重定向到 CloudFront 实例,转到 Behaviour 选项卡,选择您的 API 的路径模式(例如:/api/*) 并点击编辑按钮.

<块引用>

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

<块引用>

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

注意 2:对于那些来自 serverless 并希望在部署 lambdas 时设置二进制类型的用户,请查看此帖子:为 API 网关设置二进制媒体类型

插件:- 无服务器-apigw-二进制风俗:apigw二进制:类型:- '图像/JPEG'

cloudfront 的 serverless.yml 文件应包含:

资源:WebAppCloudFront 分布:类型:AWS::CloudFront::Distribution特性:分布配置:...缓存行为:...-#API 调用...转发值:...标题:- 授权- 接受

I cannot get python lambda to return binary data. The node-template for thumbnail images works fine but I cannot get a python lambda to work. Below is the relevant lines from my lambda. The print("image_data " + image_64_encode) line prints a base64 encoded image to the logs.

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'
    }

Any pointers to what I'm doing wrong?

解决方案

Following all the steps above didn't work on my case, because having the binary support for content-type = */* will convert all responses to binary.

My case:

  • Multiple lambda functions returning json (text), just a single lambda returning a binary file. All have lambda proxy enabled.

  • The lambdas are in an API Gateway

  • The API Gateway is behind CloudFront

Hint: I have notice an important information in the API Gateway -> Settings

Quoting:

API Gateway will look at the Content-Type and Accept HTTP headers to decide how to handle the body.

This means that the Content-Type response header must match Accept request header

Solution:

  1. Set Binary Media Types in API gateway to your mime type: image/jpg

  2. In your HTTP request set Accept: image/jpg

  3. In your HTTP response set Content-Type: image/jpg

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

  1. Next we must tell CloudFront to accept the 'Accept' header from the request. So, in CloudFront distribution, click on your API Gateway instance (ID is clickable) and once redirected to CloudFront instance go to Behaviour tab, select the path-pattern of your API (example: /api/*) and click on Edit button.

On the new screen, you have to add Accept header to Whitelist.

Note 1: If you have multiple file types, you must add them all to Binary Media Types in the API gateway settings

Note 2: For those coming from serverless and want to set the binary types when deploying your lambdas, then check this post: setting binary media types for API gateway

plugins:
  - serverless-apigw-binary

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

The serverless.yml file for cloudfront should contain:

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

相关文章