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

如何在Python中从AWS中的lambda函数返回二进制数据?,python,image,amazon-web-services,lambda,binary,Python,Image,Amazon Web Services,Lambda,Binary,我无法让python lambda返回二进制数据。工作正常,但我无法让python lambda工作。下面是我的lambda中的相关行。print(“image\u data”+image\u 64\u encode)行将base64编码的图像打印到日志中 def lambda_handler(event, context): img_base64 = event.get('base64Image') if img_base64 is None: return r

我无法让python lambda返回二进制数据。工作正常,但我无法让python lambda工作。下面是我的lambda中的相关行。
print(“image\u data”+image\u 64\u 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'
    }

有人指出我做错了什么吗?

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

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


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

据我所知,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')
})  

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

请按照此处的说明操作:

创建新方法时,请确保选中“使用Lambda代理集成”

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

导入base64
def lambda_处理程序(事件、上下文):
# ...
body=base64.b64编码(bin_数据)
返回{'isBase64Encoded':True,
“状态代码”:200,
'headers':{'Content-Type':Content\u-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\"}]"

在我的案例中,执行上述所有步骤都不起作用,因为对content type=
*/*
提供二进制支持会将所有响应转换为二进制

我的情况是:

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

  • lambda位于API网关中

  • API网关位于CloudFront后面

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

引述:

API网关将查看内容类型接受HTTP头,以决定如何处理正文

这意味着内容类型响应头必须与接受请求头匹配

解决方案:

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

  • 在HTTP请求集中
    Accept:image/jpg

  • 在HTTP响应集中
    内容类型:image/jpg

  • 接下来,我们必须告诉CloudFront接受来自请求的“accept”头。因此,在CloudFront发行版中,单击API网关实例(ID可单击),一旦重定向到CloudFront实例,转到行为选项卡,选择API的路径模式(示例:/API/*)并单击编辑按钮
  • 在新屏幕上,您必须将Accept标题添加到白名单中

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

    注2:对于那些来自无服务器的用户,如果他们想在部署lambda时设置二进制类型,请查看以下帖子:

    cloudfront的serverless.yml文件应包含:

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

    lambda在哪?你有什么办法吗?我也有同样的问题。很好的建议,但对我来说并不是很好。你能准确地告诉我你是如何编码
    base64\u编码的二进制数据的吗?
    import base64
    base64\u编码的二进制数据=base64.b64编码(bin\u数据)
    谢谢@user1495323!这很清楚。我想我缺少的是“二进制媒体类型”实际上与客户端的传入
    Accept
    头匹配,而不是您传出的
    内容类型
    头,因此我需要将
    */*
    添加到我的二进制媒体类型列表中。因此,基本上,Lambda函数将始终在JSON中接收/发送base64编码的数据。只有API网关将接收/发送客户端的二进制数据?这将返回一个0乘0的图像,我不知道我做错了什么。我首先检查image.jpg的内容,确保Lambda调用可以使用它。(我没有在示例中进行任何错误检查。)请尝试wget/curl通过API网关捕获Lambda调用的结果。谢谢,这对我有用!你知道为什么必须先将其编码为base64,然后再解码为utf-8吗?在我看来,这是先将其读取为字节,然后将其编码为base64,然后解码字节,然后解码base64。我原以为您必须切换最后两个操作,以避免混合编码?感谢您提供此解决方案。对我来说,我忘记的部分是在请求中包含
    Accept
    头。一定要检查一下!
    pip install aws-shell
    
    {
      "isBase64Encoded": True,
      "statusCode": 200,
      "headers": { "content-type": "image/jpg"},
      "body":  base64.b64encode(content_bytes).decode("utf-8")
    }
    
    plugins:
      - serverless-apigw-binary
    
    custom:
      apigwBinary:
        types:
    - 'image/jpeg'
    
    resources:
        WebAppCloudFrontDistribution:
          Type: AWS::CloudFront::Distribution
          Properties:
            DistributionConfig:
              ...
              CacheBehaviors:
                ...
                - 
                  #API calls
                  ...
                  ForwardedValues:
                    ...
                    Headers:
                      - Authorization
                      - Accept