You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Postman上传图片至Lambda再转存S3时遇文件类型不支持问题求助

问题解决:Lambda处理表单上传图片至S3后文件格式不支持

问题描述

通过Postman表单上传图片,经Lambda函数接收后存储到S3,已配置Lambda与S3的访问权限,但文件名显示正常,下载时提示“filetype not supported”。

代码问题分析

原代码中POST请求处理存在以下核心问题:

  • 手动通过body.split('image/jpeg\r\n\r\n')[1]拆分请求体,硬编码方式仅适配特定格式的multipart请求,一旦请求边界符、Content-Type稍有变化,就会导致存储的文件内容损坏(包含多余HTTP边界信息或缺失文件数据),最终无法被识别格式。
  • 固定设置ContentType='image/jpeg',无法兼容png、gif等其他图片格式。
  • 未正确解析multipart/form-data类型的表单数据,直接操作原始body存在兼容性风险。

修复后的代码

import json
import boto3
import base64
import cgi
import io

s3_client = boto3.client('s3')
BUCKET_NAME = 'u'
last_value = None

def lambda_handler(event, context):
    global last_value
    print(json.dumps(event))

    # 处理API Gateway请求
    if 'httpMethod' in event:
        if event['httpMethod'] == 'POST':
            try:
                headers = event.get('headers', {})
                body = event.get('body', '')
                
                # 解码base64编码的请求体
                if event.get('isBase64Encoded', False):
                    body = base64.b64decode(body)
                
                # 校验请求类型为multipart/form-data
                content_type = headers.get('Content-Type', '')
                if not content_type.startswith('multipart/form-data'):
                    raise ValueError("仅支持multipart/form-data类型请求")
                
                # 解析multipart表单数据
                form_data = cgi.FieldStorage(
                    fp=io.BytesIO(body),
                    headers=headers,
                    environ={'REQUEST_METHOD': 'POST'}
                )
                
                # 获取表单中的文件字段(Postman中表单键名需为'file')
                file_item = form_data.get('file')
                if not file_item:
                    raise ValueError("表单中缺少'file'字段")
                
                file_name = file_item.filename
                file_content = file_item.file.read()
                content_type = file_item.type
                
                # 上传至S3
                s3_client.put_object(
                    Bucket=BUCKET_NAME,
                    Key=file_name,
                    Body=file_content,
                    ContentType=content_type
                )
                
                last_value = file_name
                print('已上传文件:', last_value)
                return {
                    'statusCode': 200,
                    'body': json.dumps(f'文件上传成功: {last_value}')
                }
            except Exception as e:
                return {
                    'statusCode': 500,
                    'body': json.dumps(f'上传失败: {str(e)}')
                }
        
        elif event['httpMethod'] == 'GET':
            try:
                # 获取最近上传的文件
                file_name = last_value
                if not file_name:
                    raise ValueError("暂无已上传文件")
                
                s3_response = s3_client.get_object(Bucket=BUCKET_NAME, Key=file_name)
                image_data = s3_response['Body'].read()
                content_type = s3_response['ContentType']
                
                return {
                    'statusCode': 200,
                    'isBase64Encoded': True,
                    'headers': {
                        'Content-Type': content_type
                    },
                    'body': base64.b64encode(image_data).decode('utf-8')
                }
            except Exception as e:
                return {
                    'statusCode': 500,
                    'body': json.dumps(f'获取图片失败: {str(e)}')
                }
    
    # 处理S3事件
    elif 'Records' in event and event['Records'][0]['eventSource'] == 'aws:s3':
        for record in event['Records']:
            bucket_name = record['s3']['bucket']['name']
            object_key = record['s3']['object']['key']
            print(f"文件已上传至存储桶: {bucket_name}, 路径: {object_key}")
            
        return {
            'statusCode': 200,
            'body': json.dumps('S3事件处理完成')
        }

关键修复点

  • 使用Python内置cgi.FieldStorage解析multipart表单,正确提取文件二进制内容、文件名和原生Content-Type。
  • 动态设置S3对象的Content-Type,适配所有图片格式。
  • 直接使用解析后的纯净文件内容上传,避免手动拆分请求体导致的内容损坏。

Postman配置注意事项

  • 请求方法选POST,请求体选form-data。
  • 添加键名为file的字段,类型选File,选择本地图片文件上传。
  • 无需手动添加file-name头,解析器会自动从表单中提取文件名。

内容的提问来源于stack exchange,提问作者Ashish Nagmoti

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 21:57:15