使用AWS Lambda及Chalice向S3存储文件:本地正常部署后文件格式异常
解决Chalice部署Lambda后S3上传文件格式损坏问题
我之前也碰到过几乎一模一样的坑!Chalice在本地chalice local和AWS Lambda环境下处理请求的细节有差异,这就是导致文件格式不对的核心原因。下面是我踩坑后总结的解决方案:
1. 处理API Gateway的Base64编码请求体
Lambda环境中,API Gateway会默认把二进制请求体做Base64编码后再传给Lambda函数,但本地运行时Chalice直接处理原始二进制数据。如果你的代码没做解码就上传,文件会变成Base64文本格式,自然损坏。
修复代码示例:
from chalice import Chalice import base64 from chalice.app import Request import boto3 app = Chalice(app_name='file-upload-service') s3_client = boto3.client('s3') @app.route('/upload', methods=['POST'], content_types=['multipart/form-data']) def handle_upload(): req = app.current_request # 关键:判断请求体是否被Base64编码(仅Lambda环境会触发) if req.is_base64_encoded: # 解码原始请求体 decoded_body = base64.b64decode(req.raw_body) # 重新构造Request对象,用解码后的二进制数据解析multipart表单 parsed_req = Request( method=req.method, uri=req.uri, headers=req.headers, body=decoded_body, context=req.context ) file_obj = parsed_req.files.get('file') else: file_obj = req.files.get('file') if not file_obj: return {"status": "error", "msg": "No file provided"} # 直接上传二进制文件内容到S3 s3_client.put_object( Bucket='your-target-bucket', Key=file_obj.filename, Body=file_obj.read(), ContentType=file_obj.content_type ) return {"status": "success", "filename": file_obj.filename}
2. 配置API Gateway支持二进制媒体类型
如果你的上传文件是图片、PDF这类二进制格式,需要让API Gateway知道不要对这些类型的请求体做Base64编码。在Chalice的配置文件.chalice/config.json中添加二进制媒体类型配置:
{ "version": "2.0", "app_name": "file-upload-service", "stages": { "prod": { "api_gateway_stage": "prod", "binary_media_types": ["*/*"] # 支持所有类型,也可以指定具体类型如"image/jpeg", "application/pdf" } } }
配置后重新部署:chalice deploy --stage prod,这样API Gateway会直接把二进制请求体传给Lambda,避免额外的编码解码步骤。
3. 确保上传的是原始二进制数据
最后要注意:不要对file_obj.read()的结果做任何字符串转换(比如str(file_obj.read())或者.encode()),直接把二进制数据传入S3的Body参数。一旦转成字符串,文件的二进制结构就会被破坏。
按照这三步操作,应该就能解决部署后文件格式不正确的问题了!
内容的提问来源于stack exchange,提问作者Adam Liu
相关产品推荐
相关产品推荐

