借助AWS Lambda函数向Box上传文件——多部分解析问题
问题分析与修复方案
你的Lambda函数上传文件到Box后损坏,核心问题出在multipart/form-data解析逻辑错误以及二进制数据处理不当,具体问题点和修复方式如下:
核心问题
- 未处理Base64编码的请求体:API Gateway触发Lambda时,multipart/form-data的请求体默认是Base64编码的,直接将
event['body']当作字符串处理会破坏二进制文件数据。 - 手动提取boundary不可靠:通过
data.split("\r")[0][2:]获取boundary的方式容易出错,应该从content-type头中规范提取。 - 二进制数据错误编码:将
part.value用latin-1编码写入文件,会改变原始二进制内容,导致文件损坏。
修复后的代码
import os import json import boto3 import uuid import urllib3 import base64 from io import BytesIO from multipart import MultipartParser from email.parser import HeaderParser ssm = boto3.client('ssm', 'us-east-2') http = urllib3.PoolManager() def getToken(token_url): # 补充你原本的getToken实现逻辑 pass def lambda_handler(event, context): content_type = event['headers'].get('content-type', '') if content_type.startswith('multipart/form-data'): # 1. 从content-type头中规范提取boundary parser = HeaderParser() headers = parser.parsestr(f'Content-Type: {content_type}') boundary = headers.get_param('boundary') # 2. 处理Base64编码的请求体 body = event['body'] if event.get('isBase64Encoded', False): body = base64.b64decode(body) # 3. 正确解析multipart数据 p = MultipartParser(BytesIO(body), boundary) parts = p.parts() for part in parts: print("Key (Name):", part.name) if part.name == 'file': # 直接获取文件原始二进制数据,跳过不必要的编码转换 file_data = part.raw # 可选:临时文件验证(调试用,可删除) temp_file_path = '/tmp/temp_file.xlsx' with open(temp_file_path, 'wb') as temp_file: temp_file.write(file_data) # 获取Box令牌并执行上传 token_url = os.environ['TOKEN_URL'] access_token = getToken(token_url) setFileContent(access_token, file_data, f"{uuid.uuid4()}.xlsx") print('File uploaded to Box successfully') def setFileContent(token, file_data, file_name): url = "https://upload.box.com/api/2.0/files/content" headers = {"Authorization": f"Bearer {token}"} attributes = {"name": file_name, "parent": {"id": "124435"}} fields = { "attributes": json.dumps(attributes), 'file': (file_name, file_data) } response = http.request('POST', url, headers=headers, fields=fields) print(response.status)
关键修复点说明
- Base64解码处理:检查
isBase64Encoded标志,对请求体进行Base64解码,还原原始二进制数据。 - 规范提取boundary:使用
email.parser.HeaderParser从content-type头中正确提取boundary,避免手动分割的潜在错误。 - 保留原始二进制:使用
part.raw直接获取文件的原始字节数据,跳过字符串编码转换步骤,确保文件内容完整。
内容的提问来源于stack exchange,提问作者Mark
相关产品推荐
相关产品推荐

