XML文件本身是纯文本格式,无法直接嵌入图片、文档等二进制附件,但可以通过MIME多部分封装的方式实现附件的携带。SOAP协议作为基于XML的Web服务通信标准,很早就支持带附件的消息格式,将SOAP XML主体和附件分别作为MIME的不同部分进行传输,既满足结构化数据交换的需求,又能传输非文本类资源。

XML携带附件的基本原理
XML本身是标记语言,所有内容都需要符合XML的语法规范,二进制附件如果直接嵌入XML会出现编码问题,也无法被XML解析器正确识别。因此通用的做法是将XML主体和附件分开,通过MIME协议进行封装:MIME消息包含一个或多个部分,第一部分通常是SOAP XML主体,后续部分可以是任意类型的附件,各部分之间通过唯一的边界标识分隔。
SOAP带附件的消息结构组成
一个完整的SOAP带附件消息主要由以下几部分组成:
- MIME头:声明消息类型为multipart/related,指定边界字符串和各部分的Content-Type。
- SOAP XML主体部分:作为MIME的第一个部分,包含SOAP信封、请求数据,同时通过cid引用后续的附件。
- 附件部分:每个附件作为独立的MIME部分,包含自身的Content-Type和Content-ID,供SOAP主体引用。
SOAP带附件消息的MIME头示例
MIME头需要明确消息的封装类型,边界字符串用于分隔不同的部分,示例如下:
MIME-Version: 1.0 Content-Type: multipart/related; boundary="SOAP-ATTACHMENT-BOUNDARY"; type="text/xml"
SOAP XML主体结构
SOAP主体中通过<xop:Include>元素或者cid引用附件,这里的cid对应附件部分的Content-ID,示例如下:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xop="http://www.w3.org/2004/08/xop/include">
<soap:Header/>
<soap:Body>
<uploadFileRequest>
<fileName>测试文档.pdf</fileName>
<fileContent>
<xop:Include href="cid:attachment1@ippipp.com"/>
</fileContent>
</uploadFileRequest>
</soap:Body>
</soap:Envelope>
附件部分结构
附件部分需要声明自身的Content-Type和Content-ID,Content-ID需要和SOAP主体中的引用对应,示例如下:
--SOAP-ATTACHMENT-BOUNDARY Content-Type: application/pdf Content-ID: <attachment1@ippipp.com> Content-Transfer-Encoding: binary %PDF-1.4 二进制文件内容流... --SOAP-ATTACHMENT-BOUNDARY--
完整的SOAP带附件消息示例
将MIME头、SOAP主体、附件部分组合后,完整的消息格式如下:
MIME-Version: 1.0
Content-Type: multipart/related; boundary="SOAP-ATTACHMENT-BOUNDARY"; type="text/xml"
--SOAP-ATTACHMENT-BOUNDARY
Content-Type: text/xml; charset=utf-8
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xop="http://www.w3.org/2004/08/xop/include">
<soap:Header/>
<soap:Body>
<uploadFileRequest>
<fileName>测试文档.pdf</fileName>
<fileContent>
<xop:Include href="cid:attachment1@ipipp.com"/>
</fileContent>
</uploadFileRequest>
</soap:Body>
</soap:Envelope>
--SOAP-ATTACHMENT-BOUNDARY
Content-Type: application/pdf
Content-ID: <attachment1@ipipp.com>
Content-Transfer-Encoding: binary
%PDF-1.4 二进制文件内容流...
--SOAP-ATTACHMENT-BOUNDARY--
注意事项
在实际使用SOAP带附件的消息时,需要注意以下几点:
- 边界字符串不能出现在任何部分的内容中,否则会导致消息解析错误。
- 附件的Content-ID需要全局唯一,避免引用冲突。
- 如果附件是文本类型,可以根据需要选择base64编码或者binary编码,二进制文件建议使用binary编码减少开销。
- 现在的RESTful接口更多使用multipart/form-data传输文件,SOAP带附件的方式更多用于遗留的Web服务系统。