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

时间:2017-07-01 11:39:18

标签: python image amazon-web-services lambda binary

我无法让python lambda返回二进制数据。 node-template for thumbnail images工作正常,但我不能让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'
    }

指出我做错了什么?

4 个答案:

答案 0 :(得分:10)

我终于弄明白了。从python lambda返回二进制数据是可行的。

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

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

还要确保你的python lambda响应如下:

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

THEN:

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

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网关'breadcrumbs'中看到 例如:

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

THEN: 您需要'部署API'。从我发现的只是它只在部署API后才有效。

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

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

pip install aws-shell

答案 1 :(得分:4)

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

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

使用API​​网关和代理集成。

[更新]

我终于意识到该怎么做了。对于*/*类型我enabled binary support,然后返回此内容:

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

答案 2 :(得分:3)

执行上述所有步骤均不适用于我的情况,因为二进制支持content-type = */*会将所有响应转换为二进制。

我的情况:

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

  • lambda位于API网关中

  • API网关在CloudFront后面

提示: 我注意到API网关中的重要信息->设置

  

Binary support description

报价:

  

API网关将查看 Content-Type Accept HTTP标头,以决定如何处理正文。

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

匹配

解决方案:

  1. 在API网关中将二进制MEdia类型设置为您的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实例后,转到 Behaviour 标签,选择API的路径模式(例如:/ api / * ),然后点击修改按钮。
  

Example of path patterns

在新屏幕上,您必须向白名单添加 Accept (接受)标头。

  

whitelist Accept

注意1:如果您有多种文件类型,则必须将它们全部添加到API网关设置的二进制媒体类型

注意2:对于那些来自无服务器的用户,并希望在部署Lambda时设置二进制类型,请查看以下文章:setting binary media types for API gateway

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

答案 3 :(得分:1)

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

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

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