我想调用一个以 spyne 二进制类型作为参数的 Web 服务方法。但我找不到任何支持它的 python 肥皂客户端。
为了调试我的问题,我做了一个简单的 Web 服务方法,应该打印一个文件:
# @srpc(Attachment, _returns=Unicode)
@srpc(ByteArray, _returns=Unicode)
# @srpc(File, _returns=Unicode)
# @srpc(Unicode, _returns=Unicode)
def print_file(file_content):
logger.info(u"print file:\n{}\ntype:{}".format(file_content, file_content.__class__))
return u''
如您所见,我尝试了 3 种 spyne 二进制类型。对于调试,我也尝试使用 Unicode,并以 base64 传递文件内容,在这种情况下没有问题。因此,Web 服务是可操作的。
服务器端是一个 Django 应用程序和一个 spyne 应用程序。我的问题在客户端。使用suds,得到的错误非常模糊,根据论坛没有解决方案。
我使用 python 2.7 和 3.3尝试了https://wiki.python.org/moin/WebServices#SOAP上描述的所有 SOAP 客户端 。在构建请求、序列化 spyne 二进制对象时,它们都失败了。
我的最后一次尝试是使用 zeep。我用 wsdl 本地 url 实例化 zeep 客户端。抱歉,wsdl 不公开。
我用一个空的 ByteArray 调用这个方法:
param = ByteArray()
client.service.print_file(param)
捕获的异常是:
File "/usr/lib/python2.7/site-packages/zeep/client.py", line 41, in __call__
self._op_name, args, kwargs)
File "/usr/lib/python2.7/site-packages/zeep/wsdl/bindings/soap.py", line 107, in send
options=options)
File "/usr/lib/python2.7/site-packages/zeep/wsdl/bindings/soap.py", line 65, in _create
serialized = operation_obj.create(*args, **kwargs)
File "/usr/lib/python2.7/site-packages/zeep/wsdl/definitions.py", line 165, in create
return self.input.serialize(*args, **kwargs)
File "/usr/lib/python2.7/site-packages/zeep/wsdl/messages/soap.py", line 48, in serialize
self.body.render(body, body_value)
File "/usr/lib/python2.7/site-packages/zeep/xsd/elements.py", line 333, in render
self._render_value_item(parent, value)
File "/usr/lib/python2.7/site-packages/zeep/xsd/elements.py", line 354, in _render_value_item
return self.type.render(node, value)
File "/usr/lib/python2.7/site-packages/zeep/xsd/types.py", line 356, in render
element.render(parent, element_value)
File "/usr/lib/python2.7/site-packages/zeep/xsd/indicators.py", line 189, in render
element.render(parent, element_value)
File "/usr/lib/python2.7/site-packages/zeep/xsd/elements.py", line 333, in render
self._render_value_item(parent, value)
File "/usr/lib/python2.7/site-packages/zeep/xsd/elements.py", line 354, in _render_value_item
return self.type.render(node, value)
File "/usr/lib/python2.7/site-packages/zeep/xsd/types.py", line 180, in render
parent.text = self.xmlvalue(value)
File "/usr/lib/python2.7/site-packages/zeep/xsd/builtins.py", line 83, in _wrapper
return func(self, value)
File "/usr/lib/python2.7/site-packages/zeep/xsd/builtins.py", line 357, in xmlvalue
return base64.b64encode(value)
File "/usr/lib64/python2.7/base64.py", line 53, in b64encode
encoded = binascii.b2a_base64(s)[:-1]
TypeError: must be convertible to a buffer, not ModelBaseMeta
有谁知道 zeep 是否有解决方案?
也许有一个专门的 zeep 插件?
还是有其他解决方案?
也许在 C/C++ 中,编译为 python 包?
埃里克
==================================================== ==========
== 解决方案
由于我在这个问题上浪费了很多时间,这就是我的解决方案。
最后,我还需要文件名,而不仅仅是文件数据。spyne.model.binary.File 类型本来是完美的,但它不能序列化为 SOAP 格式。
感谢与 Burak 的讨论,最终的解决方案是创建一个自定义的 ComplexType,例如:
class File(ComplexModel):
filename = Unicode
data = ByteArray
在客户端使用 suds 时,将 ByteArray 字段直接替换为 base64 编码的数据:
f = File()
data = open({FILENAME}, "rb").read()
f.data = base64.b64encode(data)
在服务器端, f.data 将直接包含解码的数据。