HTTP请求边界干扰PDF解码:如何分离有效PDF内容
解决Apigee中Multipart请求里Base64编码PDF的解码问题
问题根源
你直接对整个request.content进行Base64解码,但该变量包含了Multipart请求的边界分隔符、表单字段头和Base64编码的PDF内容,解码时会把非Base64的边界/头信息一起处理,导致PDF文件损坏。
解决方案:解析Multipart结构,单独提取文件的Base64内容
要保留多文件的Multipart结构,同时正确解码每个PDF,推荐用Python脚本解析Multipart请求体,提取对应文件字段的Base64内容后单独解码,再重构合法的Multipart请求体用于后续转发。
Python策略代码实现
import base64 import email from email.parser import BytesParser from email.policy import default # 获取原请求内容和Content-Type头 request_content = flow.getVariable("request.content") content_type = flow.getVariable("request.header.Content-Type") # 解析Multipart请求结构 msg = BytesParser(policy=default).parsebytes(request_content) # 遍历所有请求部分,处理文件字段 new_parts = [] for part in msg.walk(): if part.is_multipart(): continue # 判断是否为文件上传字段 disp_header = part.get("Content-Disposition") if disp_header and "filename" in disp_header: # 提取字段内的Base64编码内容(不解码原始Payload) b64_pdf = part.get_payload(decode=False).strip() # 解码Base64为二进制PDF binary_pdf = base64.b64decode(b64_pdf) # 创建新的MIME部分,替换为二进制PDF内容 new_part = email.mime.base.MIMEBase("application", "pdf") new_part.set_payload(binary_pdf) # 保留原字段的文件名、名称等头信息 new_part.add_header("Content-Disposition", disp_header) new_part.set_type("application/pdf") new_parts.append(new_part) else: # 非文件字段直接保留原内容 new_parts.append(part) # 重构Multipart请求体,保留原边界 new_msg = email.mime.multipart.MIMEMultipart(boundary=msg.get_boundary()) for part in new_parts: new_msg.attach(part) # 将处理后的请求体存入变量,后续转发时使用 flow.setVariable("modified.request.content", new_msg.as_bytes())
代码说明
- 解析Multipart结构:利用Python内置的
email模块自动处理边界分隔和字段拆分,避免手动正则匹配的不可靠性。 - 识别文件字段:通过
Content-Disposition头中的filename标识判断是否为文件上传字段。 - 解码并替换内容:提取字段内的纯Base64字符串,解码为二进制PDF后,创建新的MIME部分替换原字段内容。
- 重构请求体:保留原Multipart边界和非文件字段,确保后续转发的请求结构符合多文件上传要求。
替代方案:正则提取单个文件的Base64(适合单文件场景)
如果仅需处理单个文件,可使用Apigee的Extract Variables策略结合正则提取纯Base64内容:
- 在策略中配置正则表达式:
--Boundaryy\r\nContent-Disposition: form-data; name="testdu12janvier"; filename="testdu12janvier.pdf"\r\n\r\n(.*?)\r\n--Boundaryy-- - 将提取到的分组内容存入变量(比如
pdf.b64.content)。 - 在Python策略中仅对该变量解码:
注意:该方法仅适用于固定字段名和边界的单文件场景,多文件场景推荐使用Python解析Multipart的方案。import base64 pdf_b64 = flow.getVariable("pdf.b64.content") pdf_binary = base64.b64decode(pdf_b64.strip()) flow.setVariable("pdfFileDecoded", pdf_binary)
内容的提问来源于stack exchange,提问作者Zyoumir
相关产品推荐
相关产品推荐

