Delphi XE2处理MTOM格式SOAP响应提取PDF失败求助
Delphi XE2处理MTOM格式SOAP响应提取PDF的解决方法
核心问题
Delphi XE2的HTTPRIO组件原生不支持MTOM,MTOM将XML结构与二进制数据(如PDF)拆分为MIME多部分消息,XML中仅通过cid引用二进制附件。直接提取XML中的cid内容或错误处理编码会导致PDF损坏。
解决方案步骤
- 获取原始HTTP响应流:在
HTTPRIO1AfterExecute事件中,获取完整的MIME多部分响应流(而非解析后的SOAP XML)。 - 解析MIME多部分消息:利用Delphi自带的Indy组件
TIdMessage拆分多部分内容,自动处理编码(如Base64)。 - 定位PDF附件:通过
Content-Type或Content-ID匹配对应的二进制附件部分。 - 保存原始二进制数据:将附件的二进制内容直接写入文件,无需额外编解码。
完整代码示例
uses IdMessage, IdMessageParts, IdGlobal, Classes; procedure TForm1.HTTPRIO1AfterExecute(const MethodName: string; SOAPResponse: TStream); var IdMsg: TIdMessage; MsgPart: TIdMessagePart; TempStream: TMemoryStream; PDFStream: TFileStream; I: Integer; begin // 复制响应流到临时内存流,避免原流指针位置问题 TempStream := TMemoryStream.Create; IdMsg := TIdMessage.Create(nil); try SOAPResponse.Position := 0; TempStream.CopyFrom(SOAPResponse, SOAPResponse.Size); TempStream.Position := 0; // 配置IdMessage自动解码附件编码(如Base64) IdMsg.NoDecode := False; IdMsg.LoadFromStream(TempStream); // 遍历所有MIME部分,寻找目标PDF for I := 0 to IdMsg.MessageParts.Count - 1 do begin MsgPart := IdMsg.MessageParts[I] as TIdMessagePart; // 方式1:通过Content-Type识别PDF if SameText(MsgPart.ContentType, 'application/pdf') then begin PDFStream := TFileStream.Create('output.pdf', fmCreate); try MsgPart.Body.SaveToStream(PDFStream); ShowMessage('PDF文件已成功保存'); finally PDFStream.Free; end; Break; end; // 方式2:通过Content-ID匹配XML中的cid(示例cid为pdf_attachment) // if MsgPart.ContentID = 'pdf_attachment' then // begin // // 保存逻辑同上 // end; end; finally IdMsg.Free; TempStream.Free; end; end;
关键注意事项
- 不要手动处理XML中的cid:
cid只是附件的引用标识,实际二进制数据存储在MIME多部分的独立附件中,不在XML内容里。 - 编码自动处理:
TIdMessage的NoDecode设为False会自动处理Content-Transfer-Encoding为base64或binary的附件,无需手动编解码。 - 响应流指针重置:操作流前必须将指针重置到起始位置,否则会读取不完整内容。
- Content-ID匹配:若XML中通过
cid:xxx引用附件,需将MsgPart.ContentID与xxx完全匹配(注意去掉cid前缀)。
内容的提问来源于stack exchange,提问作者Spyke
相关产品推荐
相关产品推荐

