我无法让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'
}
指出我做错了什么?
答案 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网关中的重要信息->设置
报价:
API网关将查看 Content-Type 和 Accept HTTP标头,以决定如何处理正文。
这意味着 Content-Type 响应标头必须与 Accept 请求标头
匹配解决方案:
在API网关中将二进制MEdia类型设置为您的mime类型:image / jpg
在您的HTTP请求中设置Accept: image/jpg
在您的HTTP响应集中设置Content-Type: image/jpg
{ "isBase64Encoded": True, "statusCode": 200, "headers": { "content-type": "image/jpg"}, "body": base64.b64encode(content_bytes).decode("utf-8") }
在新屏幕上,您必须向白名单添加 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似乎是一个很好的解决方法。最适合我。