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

如何解决AWS Lambda中用Python Requests解析Multipart/Form-Data的错误

解决AWS Lambda Function URL解析multipart/form-data的问题

问题分析

你遇到的ImproperBodyPartContentException: content does not contain CR-LF-CR-LF错误,核心原因是:

  • AWS Lambda Function URL默认会将multipart/form-data类型请求的body进行Base64编码,直接对event['body']调用encode()会导致MultipartDecoder无法识别正确的分隔符格式
  • 请求头的键存在大小写差异(如Content-Type和content-type),直接按固定键名获取可能失败

修正后的Python Lambda代码

以下代码仅依赖requests和requests-toolbelt库,实现接收字符串字段(name、date、text)及图片文件,并将图片保存为PNG格式到Lambda的/tmp目录:

import json
import base64
import requests
from requests_toolbelt.multipart import decoder

def lambda_handler(event, context):
    try:
        # 处理Base64编码的请求体
        body = event['body']
        if event.get('isBase64Encoded', False):
            body = base64.b64decode(body)
        
        # 兼容大小写的请求头获取
        content_type = None
        for key, value in event['headers'].items():
            if key.lower() == 'content-type':
                content_type = value
                break
        if not content_type:
            return {
                'statusCode': 400,
                'body': json.dumps({'error': 'Missing Content-Type header'})
            }
        
        # 解析multipart/form-data
        data = decoder.MultipartDecoder(body, content_type)
        
        # 存储表单字段和文件内容
        form_data = {}
        image_content = None
        
        for part in data.parts:
            # 解析Content-Disposition头
            disp_header = part.headers[b'content-disposition'].decode('utf-8')
            # 提取字段名
            name_start = disp_header.find('name="') + 6
            name_end = disp_header.find('"', name_start)
            field_name = disp_header[name_start:name_end]
            
            # 判断是否为文件字段
            if 'filename=' in disp_header:
                image_content = part.content
            else:
                # 解析字符串字段
                form_data[field_name] = part.content.decode('utf-8')
        
        # 验证必要字段
        required_fields = ['name', 'date', 'text']
        missing_fields = [f for f in required_fields if f not in form_data]
        if missing_fields:
            return {
                'statusCode': 400,
                'body': json.dumps({'error': f'Missing required fields: {", ".join(missing_fields)}'})
            }
        
        # 将图片保存为PNG到/tmp目录
        if image_content:
            save_path = '/tmp/uploaded_image.png'
            with open(save_path, 'wb') as f:
                f.write(image_content)
            print(f'图片已保存到: {save_path}')
        else:
            return {
                'statusCode': 400,
                'body': json.dumps({'error': 'Missing image file'})
            }
        
        # 返回成功响应
        return {
            'statusCode': 200,
            'body': json.dumps({
                'message': '请求处理成功',
                'received_data': form_data,
                'image_saved': True
            })
        }
    
    except Exception as e:
        return {
            'statusCode': 500,
            'body': json.dumps({'error': str(e)})
        }

关键修改点说明

  1. Base64解码处理:通过event['isBase64Encoded']判断并解码请求体,这是解决核心错误的关键
  2. 大小写兼容的请求头获取:遍历headers并忽略键的大小写,避免因请求头键名大小写不一致导致的错误
  3. 通用字段解析逻辑:不再硬编码字段判断,而是从Content-Disposition头中提取字段名,适配不同的表单字段
  4. 强制PNG格式保存:直接将图片内容写入/tmp/uploaded_image.png,确保输出为PNG格式
  5. 异常处理与参数校验:添加必要的字段校验和异常捕获,返回更友好的错误信息
  6. 前端请求优化提示:你的React前端代码无需修改,但注意axios会自动处理multipart/form-data的边界符,不需要手动设置Content-Type(手动设置可能会丢失边界符信息),可以修改为:
    export async function postFormData(url, form) {
      const response = await axios.post(url, form);
      return response.data;
    }
    

内容的提问来源于stack exchange,提问作者Asif Alam

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 21:47:00