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

如何在SOAP XML Payload中正确传递字节格式的objectZippedData?

解决SOAP请求中objectZippedData字段格式冲突问题

问题背景

我尝试向SOAP接口传入XML payload,其中objectZippedData字段要求必须为字节格式,但遇到两个矛盾问题:

  • 传入字符串格式的编码值时,请求执行失败
  • 直接传入字节格式数据时,触发Python错误:TypeError: can only concatenate str (not "bytes") to str

相关代码如下:

def getSoapResponse(Envelope, url, action):
    try:
        envelope = Envelope
        # Create and register opener. Requires proxy when behind a firewall
        opener = urllib.request.build_opener(urllib.request.HTTPHandler(), urllib.request.HTTPSHandler(),
                                             urllib.request.ProxyHandler())
        urllib.request.install_opener(opener)
        # Create request for the service call
        request = urllib.request.Request(url)

        # Configure the request content type to be xml
        request.add_header("Content-Type", 'application/soap+xml;charset=utf-8')

        # Set the SOAP action to be invoked; while the call works without this, the value is expected to be set based on standards
        request.add_header("SOAPAction", action)

        # Write the xml payload to the request
        request.data = envelope.encode()
        
        handle = urllib.request.urlopen(request, cafile=certifi.where())
            
        # Get the response and process it
        xmlString = (handle.read(2000).decode('utf-8'))
        if action != "uploadObjectInSession":
            # Convert the response into XML tree structure
            sessionxml = fromstring(xmlString)
            # Get the session value from the XML tree
            ReturnVal = sessionxml[0][0][0].text if action == 'login' else 'Success'
            return (ReturnVal)
        else:
            return "Success"
    except Exception as err:
        print("getSoapResponse - Error occurred; Message ", str(err))
        print("===============================================================")
        return "Error"

def uploadSession(catFile, Target):
    try:
       with open(catFile, 'rb') as f:
           bytes_encoded = base64.b64encode(f.read())
           string_encoded = bytes_encoded.decode()
           f.close()
    except IOError:
       return "Error"

new_Envelope = """<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:v2="http://xmlns.oracle.com/oxp/service/v2">
        <soapenv:Header/>
        <soapenv:Body>
            <v2:uploadObjectInSession>
                <v2:reportObjectAbsolutePathURL>""" + Target + """</v2:reportObjectAbsolutePathURL>
                <v2:objectType>xdoz</v2:objectType>
                <v2:objectZippedData>""" + string_encoded + """</v2:objectZippedData>
                <v2:bipSessionToken>""" + target_sessionid + """</v2:bipSessionToken>
            </v2:uploadObjectInSession>
        </soapenv:Body>
        </soapenv:Envelope> """

Final = getSoapResponse(Envelope=new_Envelope, url, action='uploadObjectInSession')
    if Final=="Error":
       print("FAILURE")
       return "Error"
    else:
       print(Final)
       return "Success"

触发的错误信息:

new_Envelope = """<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:v2="http://xmlns.oracle.com/oxp/service/v2">
TypeError: can only concatenate str (not "bytes") to str

核心问题分析

  1. 函数返回值缺失:uploadSession函数生成了base64编码字符串string_encoded,但未返回该值,导致后续XML拼接时变量值异常或未定义。
  2. XML格式限制:XML是纯文本格式,无法直接嵌入字节数据,服务端要求的"字节格式"实际是指经过base64编码的字符串(服务端接收后会自行解码为字节)。
  3. 字符串拼接风险:直接用字符串拼接构建XML,容易出现特殊字符未转义的问题,破坏XML结构导致请求失败。

具体修复步骤

1. 修复uploadSession函数,返回正确编码值

import base64

def uploadSession(catFile):
    try:
        with open(catFile, 'rb') as f:
            # 读取文件字节并做base64编码,再转成UTF-8字符串
            bytes_encoded = base64.b64encode(f.read())
            return bytes_encoded.decode('utf-8')
    except IOError:
        return "Error"

注:移除了未使用的Target参数,让函数专注于文件编码逻辑。

2. 使用XML库构建payload,避免转义问题

推荐用xml.etree.ElementTree构建XML,自动处理特殊字符转义,确保XML结构合法:

import xml.etree.ElementTree as ET

# 调用uploadSession获取编码后的字符串
string_encoded = uploadSession(catFile)
if string_encoded == "Error":
    print("文件读取或编码失败")
    exit()

# 注册XML命名空间
soapenv = "http://schemas.xmlsoap.org/soap/envelope/"
v2 = "http://xmlns.oracle.com/oxp/service/v2"
ET.register_namespace('soapenv', soapenv)
ET.register_namespace('v2', v2)

# 逐层构建XML结构
envelope = ET.Element(f"{{{soapenv}}}Envelope")
ET.SubElement(envelope, f"{{{soapenv}}}Header")
body = ET.SubElement(envelope, f"{{{soapenv}}}Body")
upload_obj = ET.SubElement(body, f"{{{v2}}}uploadObjectInSession")

# 添加各个字段
ET.SubElement(upload_obj, f"{{{v2}}}reportObjectAbsolutePathURL").text = Target
ET.SubElement(upload_obj, f"{{{v2}}}objectType").text = "xdoz"
ET.SubElement(upload_obj, f"{{{v2}}}objectZippedData").text = string_encoded
ET.SubElement(upload_obj, f"{{{v2}}}bipSessionToken").text = target_sessionid

# 转换为XML字符串
new_Envelope = ET.tostring(envelope, encoding='utf-8', method='xml').decode('utf-8')

3. 修正getSoapResponse调用参数

确保调用时参数顺序和格式正确:

Final = getSoapResponse(Envelope=new_Envelope, url=your_service_url, action='uploadObjectInSession')
if Final == "Error":
    print("FAILURE")
else:
    print(Final)

注:替换your_service_url为实际的SOAP接口地址。

验证逻辑

当前getSoapResponse函数中request.data = envelope.encode()是正确的,它会把XML字符串转成UTF-8字节发送给服务端,符合application/soap+xml的请求格式要求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 03:05:41