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

从SOAP响应提取二进制转Base64时文件不完整问题排查

WSO2 Integration Studio 8.1.0 提取MTOM SOAP响应完整二进制数据转Base64问题

问题场景

在WSO2 Integration Studio 8.1.0中,尝试从MTOM格式的SOAP响应提取二进制数据并转换为Base64字符串,但仅能获取部分数据。SOAP响应包含xop:Include引用的二进制附件,文件总大小4586622字节,缓冲大小1048576字节。使用以下两种方式均得到不完整或损坏的Base64字符串:

<property expression="$body/fn:GetContentResponse/fn:ContentResponse/fn:Content/fn:Binary" name="DataBase64" scope="default" type="STRING" xmlns:fn="http://www.filenet.com/ns/fnce/2006/11/ws/schema"/>
<property expression="base64Encode($body/fn:GetContentResponse/fn:ContentResponse/fn:Content/fn:Binary)" name="DataBase64" scope="default" type="STRING" xmlns:fn="http://www.filenet.com/ns/fnce/2006/11/ws/schema"/>

问题原因

  1. MTOM解析未启用:默认情况下Synapse未自动解析MTOM格式的xop:Include引用,直接提取Binary节点只能拿到引用标识,而非实际二进制内容。
  2. 分块响应未处理:SOAP响应的continueFrom参数(offset=1048576;id={...})表明服务采用分块返回策略,当前仅获取了第一块(1048576字节)数据,未循环请求剩余部分。

解决步骤

1. 启用MTOM解析

在序列中添加属性开启MTOM支持,让Synapse自动解析xop:Include并加载附件内容:

<property name="enableMTOM" value="true" scope="axis2"/>

2. 处理分块响应,循环获取完整数据

通过while mediator循环调用服务,直到continueFrom为空,拼接每次返回的二进制数据后再转换为Base64。修改后的核心逻辑如下:

<!-- 初始化存储完整二进制数据的属性 -->
<property name="FullBinaryData" scope="default" type="OM"/>
<property name="ContinueToken" expression="$body/fn:GetContentResponse/fn:ContentResponse/@continueFrom" scope="default" type="STRING" xmlns:fn="http://www.filenet.com/ns/fnce/2006/11/ws/schema"/>

<!-- 循环获取分块数据 -->
<while xmlns:fn="http://www.filenet.com/ns/fnce/2006/11/ws/schema" expression="boolean(get-property('ContinueToken')) != ''">
    <sequence>
        <!-- 构建带continueFrom参数的请求 -->
        <payloadFactory media-type="xml">
            <format>
                <soapenv:Envelope xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
                    <soapenv:Header>
                        <Security xmlns="http://schemas.xmlsoap.org/ws/2002/12/secext">
                            <hd:UsernameToken xmlns:hd="http://schemas.xmlsoap.org/ws/2002/12/secext">
                                <hd:Username>$1</hd:Username>
                                <hd:Password>$2</hd:Password>
                            </hd:UsernameToken>
                        </Security>
                    </soapenv:Header>
                    <soapenv:Body>
                        <p857:GetContentRequest validateOnly="0" xmlns:p857="http://www.filenet.com/ns/fnce/2006/11/ws/schema">
                            <p857:ContentRequest continueFrom="$6" cacheAllowed="1" id="1" startOffset="0">
                                <p857:SourceSpecification classId="$4" itemIndex="0" objectId="$5" objectStore="$3" serializationDuplicate="0" xsi:type="p857:ObjectSpecification"/>
                                <p857:ElementSpecification elementSequenceNumber="0" itemIndex="0"/>
                            </p857:ContentRequest>
                        </p857:GetContentRequest>
                    </soapenv:Body>
                </soapenv:Envelope>
            </format>
            <args>
                <arg evaluator="xml" expression="get-property('Username')"/>
                <arg evaluator="xml" expression="get-property('Password')"/>
                <arg evaluator="xml" expression="get-property('ObjectStore')"/>
                <arg evaluator="xml" expression="get-property('DocumentClass')"/>
                <arg evaluator="xml" expression="get-property('DocumentId')"/>
                <arg evaluator="xml" expression="get-property('ContinueToken')"/>
            </args>
        </payloadFactory>
        <call-template target="StorageEndpointTemplate"/>
        <!-- 提取当前块的二进制数据并拼接到完整数据中 -->
        <property name="CurrentBinary" expression="$body/fn:GetContentResponse/fn:ContentResponse/fn:Content/fn:Binary" scope="default" type="OM"/>
        <script language="js"><![CDATA[
            var fullData = mc.getProperty('FullBinaryData');
            var currentData = mc.getProperty('CurrentBinary');
            if (fullData == null) {
                fullData = currentData;
            } else {
                fullData.appendChild(currentData.getFirstOMChild());
            }
            mc.setProperty('FullBinaryData', fullData);
        ]]></script>
        <!-- 更新continueToken,若为空则退出循环 -->
        <property name="ContinueToken" expression="$body/fn:GetContentResponse/fn:ContentResponse/@continueFrom" scope="default" type="STRING"/>
    </sequence>
</while>

<!-- 将完整二进制数据转换为Base64 -->
<property expression="base64Encode(get-property('FullBinaryData'))" name="DataBase64" scope="default" type="STRING"/>

3. 注意事项

  • 处理大文件时需关注内存占用,避免内存溢出;若文件过大,建议采用流处理而非全量加载到内存。
  • 需确保后端服务支持分块续传逻辑,continueFrom参数格式需与服务要求一致。

内容的提问来源于stack exchange,提问作者Mahmoud Saleh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 02:10:59