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

Delphi XE2处理MTOM格式SOAP响应提取PDF失败求助

Delphi XE2处理MTOM格式SOAP响应提取PDF的解决方法

核心问题

Delphi XE2的HTTPRIO组件原生不支持MTOM,MTOM将XML结构与二进制数据(如PDF)拆分为MIME多部分消息,XML中仅通过cid引用二进制附件。直接提取XML中的cid内容或错误处理编码会导致PDF损坏。

解决方案步骤

  1. 获取原始HTTP响应流:在HTTPRIO1AfterExecute事件中,获取完整的MIME多部分响应流(而非解析后的SOAP XML)。
  2. 解析MIME多部分消息:利用Delphi自带的Indy组件TIdMessage拆分多部分内容,自动处理编码(如Base64)。
  3. 定位PDF附件:通过Content-Type或Content-ID匹配对应的二进制附件部分。
  4. 保存原始二进制数据:将附件的二进制内容直接写入文件,无需额外编解码。

完整代码示例

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 14:37:11