如何用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 }) }
关键修正点说明
- 解析Lambda请求体:使用
requests_toolbelt的MultipartDecoder解析客户端上传的原始multipart数据,先解码base64格式的event['body'] - 正确构造转发请求:通过
requests的files参数自动生成符合规范的multipart/form-data请求,无需手动拼接boundary和头部信息 - 清理不必要的请求头:移除浏览器端的
cookie和x-hubspot-csrf-hubspot头,避免Lambda环境与浏览器环境的头信息冲突 - 文件内容处理:将提取的二进制文件内容包装为
BytesIO对象,适配requests的files参数要求
内容的提问来源于stack exchange,提问作者himan
相关产品推荐
相关产品推荐

