编写Lambda函数上传文件至S3桶遇KeyError问题求助
错误原因分析
- event结构访问错误:Lambda的
event是字典类型,不是对象,用event.body会触发AttributeError;改成event['body']后报KeyError,说明触发Lambda的请求(比如API Gateway调用、控制台测试)传入的event里根本没有body字段,或者字段结构不符合预期。 - S3操作逻辑错误:
s3.put_object()是上传文件到S3的方法,它的返回结果里没有Body字段——这个方法只返回上传成功的元数据(比如ETag),你试图读取response['Body']属于逻辑错误。 - 返回值逻辑错误:上传完成后不需要返回文件内容,应该返回上传成功的标识或文件的访问地址。
修复后的代码(以API Gateway触发上传为例)
假设你通过API Gateway的POST请求上传JPG图片,且API Gateway已配置支持二进制媒体类型,修复后的代码如下:
import base64 import boto3 import uuid s3 = boto3.client('s3') BUCKET_NAME = 'your-s3-bucket-name' # 替换成你的S3桶名 def lambda_handler(event, context): # 处理请求中的文件内容 try: # 从API Gateway的event中获取base64编码的图片数据 encoded_image = event['body'] # 解码为二进制格式,用于上传S3 image_data = base64.b64decode(encoded_image) except KeyError: return { 'statusCode': 400, 'headers': { "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Headers": "Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token", "Access-Control-Allow-Methods": "*", "Access-Control-Allow-Credentials": "true" }, 'body': '请求缺少文件内容(body字段)' } except Exception as e: return { 'statusCode': 400, 'headers': { "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Headers": "Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token", "Access-Control-Allow-Methods": "*", "Access-Control-Allow-Credentials": "true" }, 'body': f'文件解码失败: {str(e)}' } # 生成唯一文件名,避免重复覆盖 file_key = f"{str(uuid.uuid4())}.jpg" try: # 上传文件到S3 s3.put_object( Bucket=BUCKET_NAME, Key=file_key, Body=image_data, ContentType='image/jpg' # 指定文件类型,帮助S3正确识别 ) # 生成文件访问地址(前提是桶配置了公开可读,或可替换为预签名URL) file_url = f"https://{BUCKET_NAME}.s3.amazonaws.com/{file_key}" return { 'statusCode': 200, 'headers': { "Content-Type": "application/json", "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Headers": "Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token", "Access-Control-Allow-Methods": "*", "Access-Control-Allow-Credentials": "true" }, 'body': f'文件上传成功!访问地址: {file_url}' } except Exception as e: return { 'statusCode': 500, 'headers': { "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Headers": "Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token", "Access-Control-Allow-Methods": "*", "Access-Control-Allow-Credentials": "true" }, 'body': f'上传失败: {str(e)}' }
关键注意事项
- API Gateway配置:必须在API Gateway的设置中添加
image/jpg到二进制媒体类型列表,否则API Gateway会把二进制图片转成字符串,导致解码失败。 - Lambda权限:确保Lambda的执行角色拥有
s3:PutObject权限,允许操作目标S3桶。 - 控制台测试格式:如果直接在Lambda控制台测试,需要构造符合API Gateway格式的event,示例:
{ "body": "你的JPG图片base64编码内容", "isBase64Encoded": true } - 文件类型校验:如果需要限制上传文件类型,可以在代码中添加对文件头或请求
Content-Type的校验,避免非JPG文件上传。
内容的提问来源于stack exchange,提问作者Obtas
相关产品推荐
相关产品推荐

