在Ruby中使用SOAP请求发送文件

时间:2018-08-21 17:01:37

标签: ruby-on-rails ruby soap savon

我正在尝试使用Savon gem发送pdf文件以及SOAP请求。
我发现的所有类似问题都是5岁以上(Savon v1)或没有任何答案。

在SoapUI中测试请求时,我能够成功发送带有以下请求的文件+附件中的文件:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ws="link" xmlns:nir="link">
   <soapenv:Header>
      <ws:nvheader>
         <ws:nvcommand>
            <ws:nv_user>nv_user</ws:nv_user>
            <ws:nv_password>nv_password</ws:nv_password>
         </ws:nvcommand>
      </ws:nvheader>
   </soapenv:Header>
   <soapenv:Body>
      <ws:order_create_IN>
         <ws:action type="string">ORDER_CREATE</ws:action>>
         <ws:document type="file" extension="pdf" prefix="" suffix="">
            <nir:data>cid:pdf_file_name.pdf</nir:data>
         </ws:document>
         <ws:document_name type="string">df_file_name.pdf</ws:document_name>
         <ws:get_proof type="string">NO</ws:get_proof>
         <ws:identifier type="indstringlist" case-sensitive="?">
            <nir:data key="LOGIN">login</nir:data>
            <nir:data key="PASSWORD">password</nir:data>
         </ws:identifier>
         <ws:mailing_type type="string">UNIQUE</ws:mailing_type>
         <ws:service_profile type="indstringlist" case-sensitive="?">
            <nir:data key="service_id">MAIL</nir:data>
         </ws:service_profile>
      </ws:order_create_IN>
   </soapenv:Body>
</soapenv:Envelope>

我尝试使用Savon发出此请求的内容:

  • 我从github获得了最新版本的Savon gem,它具有多部分请求发送选项https://github.com/savonrb/savon/pull/761
  • 尝试遵循此示例lib/savon/options.rb
  • 我最近的尝试是这样的:

    client = Savon.client(wsdl: "wsdl_link",
                  convert_request_keys_to: :none, logger: Rails.logger,
                  log_level: :debug,
                  log: true,
                  pretty_print_xml: true)
    
    soap_header = { nvheader:
                    { nvcommand:
                          { nv_user: ENV["postgreen_nv_user"],
                            nv_password: ENV["postgreen_nv_pwd"] } } }
    
    body = "<ws:action type=\"string\">ORDER_CREATE</ws:action>>
            <ws:document type=\"file\" extension=\"pdf\" prefix=\"\" suffix=\"\">
               <nir:data>cid:pdf_file_name.pdf</nir:data>
            </ws:document>
            <ws:document_name type=\"string\">pdf_file_name.pdf</ws:document_name>
            <ws:get_proof type=\"string\">NO</ws:get_proof>
            <ws:identifier type=\"indstringlist\" case-sensitive=\"?\">
               <nir:data key=\"LOGIN\">login</nir:data>
               <nir:data key=\"PASSWORD\">password</nir:data>
            </ws:identifier>
            <ws:mailing_type type=\"string\">UNIQUE</ws:mailing_type>
            <ws:service_profile type=\"indstringlist\" case-sensitive=\"?\">
               <nir:data key=\"service_id\">MAIL</nir:data>
            </ws:service_profile>"
    
    response = client.call(:order_create,
                       soap_header: soap_header,
                       message: body,
                       attachments: { 'pdf_file_name.pdf' => 'storage/pdf_file_name.pdf' })
    

如果我发送的请求中没有“附件”,则会得到响应(说没有文件)。
但是,当我将相同的请求与文件一起发送时,会收到一般错误响应,好像它根本无法理解该请求。

在日志中,对于不带附件的请求,我有以下内容:

SOAP request: Endpoint Link
SOAPAction: "order_create"
Content-Type: text/xml;charset=UTF-8
Content-Length: 2092
<?xml version="1.0" encoding="UTF-8"?>
...
--- "my xml message" ---
...
HTTPI /peer POST request to rct.post-green.net (net_http)
SOAP response (status 200)
date: Tue, 21 Aug 2018 12:18:54 GMT
server: NIRVA HTTP server
cache-control: no-cache
content-type: text/xml
expires: Wed, 26 Feb 1997 08:21:57 GMT
pragma: no-cache
set-cookie: NvSessionId=; expires=Thu, 01-Jan-1970 00:00:00 GMT
vary: Accept-Encoding
content-length: 906
...
--- "xml response message" ---
...

这是带有附件的请求:

SOAP request: Endpoint Link
SOAPAction: "order_create"
Content-Type: multipart/related; boundary="--==_mimepart_5b7c03832ef1_24772b1c76b4a65010330"; type="text/xml"; start="<soap-request-body@soap>"
Content-Length: 207653
<?xml version="1.0"?>
...
--- "Nothing there as if there's no message or it's too large to show" ---
...
HTTPI /peer POST request to rct.post-green.net (net_http)
SOAP response (status 500)
date: Tue, 21 Aug 2018 12:20:19 GMT
server: Apache
last-modified: Fri, 19 May 2017 12:14:25 GMT
etag: "8df-54fdf7660c649"
accept-ranges: bytes
content-length: 2271
connection: close
content-type: text/html
...
--- "html response message" ---
...

所以最后我有点迷茫,我尝试了2-3天的不同方法,但现在没有成功。

有人对此有解决方案吗?也许还有另一种方法/宝石可以实现这一目标?

1 个答案:

答案 0 :(得分:0)

您应该尝试将文件添加到xml请求中,从而将文件转换为Base64文件。

file_data = Base64.encode64(File.binread("/path/to/your/file"))

file_data集成到您的xml中,您的完整请求将如下所示:

body = "<ws:action type=\"string\">ORDER_CREATE</ws:action>>
    <ws:document type=\"file\" extension=\"pdf\" prefix=\"\" suffix=\"\">
       <nir:data>#{file_data}</nir:data>
    </ws:document>
    <ws:document_name type=\"string\">pdf_file_name.pdf</ws:document_name>
    <ws:get_proof type=\"string\">NO</ws:get_proof>
    <ws:identifier type=\"indstringlist\" case-sensitive=\"?\">
       <nir:data key=\"LOGIN\">login</nir:data>
       <nir:data key=\"PASSWORD\">password</nir:data>
    </ws:identifier>
    <ws:mailing_type type=\"string\">UNIQUE</ws:mailing_type>
    <ws:service_profile type=\"indstringlist\" case-sensitive=\"?\">
       <nir:data key=\"service_id\">MAIL</nir:data>
    </ws:service_profile>"

在您的client.call(:order_create, soap_header: soap_header, message: body)

这应该有效!