soap不支持直接将xml文件塞入soap:body,必须用mtom或swa附件机制;mtom是主流正统方案,需wsdl正确声明xmime类型并启用工具mtom选项;swa需手动构造mime,严守content-id与cid:引用一致、编码及边界规范;服务端解析须流式读取attachmentdatasource,校验content-type,避免乱码或oom。

SOAP本身不支持“XML文件当附件”这种直觉操作
不能把一个config.xml直接塞进soap:Body里当参数传——这不是规范,服务端大概率解析失败,或被当成普通字符串处理。SOAP协议设计上,soap:Body只承载结构化XML内容,不是文件传输通道。
真要传XML文件(比如报文模板、配置快照、XSD校验文件),必须走标准附件机制:用MIME multipart/related封装,把原始XML作为独立part,再在SOAP体中用引用方式关联。
- 硬塞Base64字符串进XML字段 → 体积膨胀33%,易触发服务端长度限制或XML解析器OOM
- 没设
Content-ID或ID不匹配 → 服务端找不到附件,返回Invalid xop:Include或空指针 - WSDL没声明
xmime:expectedContentTypes→ SoapUI等工具无法自动启用MTOM,灰显选项,只能手动拼Raw
MTOM是当前最靠谱的XML附件方案
MTOM(XML-binary Optimized Packaging)不是“可选技巧”,而是WS-I和主流服务框架(Axis2、.NET WCF、Apache CXF)默认支持的正统路径。它把SOAP XML保留在主part,二进制内容(包括XML文件)单独拆成application/octet-stream part,靠xop:Include按cid:引用——语义清晰、性能好、不乱码。
关键前提是WSDL得写对:
-
<element name="attachment" type="xsd:base64Binary" xmime:expectedcontenttypes="text/xml"></element>—— 缺xmime命名空间或类型声明,MTOM就启动不了 - SoapUI里右键选
MTOM/XOP后,字段填file://C:/data/template.xml(注意双斜杠和绝对路径) - 项目属性必须勾选
Enable MTOM,否则Raw标签页看不到multipart/related结构
手动构造SWA请求时,边界符和Content-ID是生死线
当服务端老旧、只认SOAP with Attachments(SWA),或WSDL缺失附件定义时,就得切Raw模式手写MIME。这不是拼JSON,错一个字符就整个请求被拒。
最常翻车的是这三处:
-
Content-Type: multipart/related; type="text/xml"; start="<rootpart>"</rootpart>——start值必须和第一个part的Content-ID完全一致(含尖括号) - 附件part的
Content-ID如<config.xml></config.xml>,SOAP Body里就得写<include href="cid:config.xml@soapui.org"></include>,少cid:前缀必失败 - XML文件不能直接粘二进制 —— SoapUI不支持,得先Base64编码,再以
Content-Transfer-Encoding: base64+Content-Type: text/xml放进去
服务端解析附件容易漏掉DataSource提取这步
很多Java服务用javax.activation.DataHandler收附件,但光拿到DataHandler不够。常见错误是直接调getContent()转String,结果XML里的中文变乱码,或遇到大文件OOM。
正确姿势是:
- 从
AttachmentDataSource获取InputStream,流式读取,不全加载进内存 - 检查
getContentType()是否为text/xml,别把PDF当XML解析 - 禁用MTOM时,服务端可能把整个MIME体当XML字符串喂给SAX解析器 → 直接抛
org.xml.sax.SAXParseException: Content is not allowed in prolog
真正难的从来不是发出去,是服务端能不能干净地把那个template.xml从multipart里捞出来、不丢字节、不改编码、不卡死。这一环断了,前面所有MTOM配置都白搭。










