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

如何用Python Lambda函数向外部API上传PDF文件?

从AWS Lambda向外部API转发multipart/form-data文件的解决方案

问题背景

在AWS Lambda中接收客户端上传的PDF文件后,尝试转发到HubSpot的文件上传API时,收到415 Media Type not supported错误。客户端到Lambda的上传流程正常,但转发请求时因格式不符合要求导致失败——当前请求体以JSON字节形式发送,而非API所需的multipart/form-data表单格式。

原代码核心问题

  • TYPE-1调用:注释了files参数,调用时未定义该变量,无法传递文件内容
  • TYPE-2调用:直接将event['body']编码发送,未解析客户端上传的multipart数据,导致请求格式错误
  • 未处理API Gateway传递的base64编码请求体(二进制文件在Lambda的event['body']中是base64格式)

修正后的实现代码

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

def lambda_handler(event, context):
    # 解析客户端上传的multipart/form-data请求
    content_type = event['headers']['content-type']
    # 解码API Gateway传递的base64格式请求体
    raw_body = base64.b64decode(event['body'])
    # 解析multipart数据
    multipart_decoder = decoder.MultipartDecoder(raw_body, content_type)

    # 提取文件和表单字段
    file_data = None
    file_name = None
    form_data = {}
    for part in multipart_decoder.parts:
        disp_header = part.headers[b'Content-Disposition'].decode('utf-8')
        field_name = disp_header.split('name="')[1].split('"')[0]
        
        if 'filename' in disp_header:
            # 提取文件信息
            file_name = disp_header.split('filename="')[1].split('"')[0]
            file_data = part.content
        else:
            # 提取普通表单字段
            form_data[field_name] = part.content.decode('utf-8')

    # 目标HubSpot API地址
    target_url = "https://app.hubspot.com/api/filemanager/api/v3/files/upload?portalId=XXXXXX"
    
    # 构造转发的表单参数
    payload = {
        'options': json.dumps({"access": "PUBLIC_NOT_INDEXABLE"}),
        'folderPath': "postman_upload"
    }
    # 构造文件参数:(文件名, 文件IO对象, 内容类型)
    files = [
        ('file', (file_name, BytesIO(file_data), 'application/pdf'))
    ]
    
    # 请求头:移除浏览器端的cookie和csrf头,仅保留必要的授权头
    headers = {
        'authorization': 'Bearer pbl-na1-c23b6031-7da9-4e7d-9516-6c58vc7cd0dc'
    }
    
    # 发送multipart/form-data请求
    api_response = requests.post(target_url, headers=headers, data=payload, files=files)
    
    print(f"API响应状态码: {api_response.status_code}")
    print(f"API响应内容: {api_response.text}")
      
    return {
        'statusCode': api_response.status_code,
        'body': json.dumps({
            'message': '文件转发完成',
            'api_response': api_response.text
        })
    }

关键修正点说明

  1. 解析Lambda请求体:使用requests_toolbelt的MultipartDecoder解析客户端上传的原始multipart数据,先解码base64格式的event['body']
  2. 正确构造转发请求:通过requests的files参数自动生成符合规范的multipart/form-data请求,无需手动拼接boundary和头部信息
  3. 清理不必要的请求头:移除浏览器端的cookie和x-hubspot-csrf-hubspot头,避免Lambda环境与浏览器环境的头信息冲突
  4. 文件内容处理:将提取的二进制文件内容包装为BytesIO对象,适配requests的files参数要求

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 10:45:35