代码之家  ›  专栏  ›  技术社区  ›  RubyRedGrapefruit

我如何用Ruby读取这个二进制XML响应?

  •  0
  • RubyRedGrapefruit  · 技术社区  · 8 年前

    我正在尝试读取来自marketplace web服务的响应。来自该web服务的每个其他响应都以XML格式返回。然而,这个特定的调用请求文件下载。我不熟悉它被退回的方式。在查看内容之后,有XML和编码的二进制数据,它们作为某种附件存在其中。

      begin
        response = Net::HTTP.start(url.host, url.port, :use_ssl => url.scheme == 'https') do |http|
          http.verify_mode = OpenSSL::SSL::VERIFY_NONE
          http.request(request)
        end
      rescue Errno::ECONNRESET => e
        count += 1
        retry unless count > 10
        puts "Tried 10 times and couldn't get #{url.host}: #{e}"
      end
    

    response.body 看起来像:

    --MIMEBoundaryurn_uuid_AF2837F4196B2631EC15070889135182607126
    Content-Type: application/xop+xml; charset=utf-8; type="text/xml"
    Content-Transfer-Encoding: binary
    Content-ID: <0.urn:uuid:AF2837F4196B2631EC15070889135182607127>
    
    <?xml version='1.0' encoding='UTF-8'?>
    <downloadFileResponse xmlns="http://www.marketplace.com/marketplace/services">
      <ack>Success</ack>
      <version>1.1.0</version>
      <timestamp>2017-10-04T03:48:33.518Z</timestamp>
      <fileAttachment>
        <Size>25895</Size>
        <Data><xop:Include xmlns:xop="http://www.w3.org/2004/08/xop/include" href="cid:urn:uuid:E3A8215C82DBC51E6D1507090865513"/></Data>
      </fileAttachment>
    </downloadFileResponse>
    
    --MIMEBoundaryurn_uuid_AF2837F4196B2631EC15070889135182607126
    Content-Type: application/zip
    Content-Transfer-Encoding: binary
    Content-ID: <urn:uuid:E3A8215C82DBC51E6D1507090865513>
    
    PK&úCKÃEK¬gdi∂6509805153_report.xmlUT   hH‘YhH‘Yux00ÏùÎs‚8∂¿ø˜_°€üÓ≠=-â Ù6ÚÍ< ›”≥µïr@   NåÕ⁄&è˘ÎØÑÅêàçÕ‡…¶+ùnåd=|Œ—œÁ˱ۜáæÓT:æ˜Îg¥?Âu¸Æ„]ˇ˙y]ïƒÁ~˘¥≥;tokvd◊:=€ªVM|/T!–˘ΩP'
    º≤∫¥Àˆ¿ Àj˜x◊U’ÔÎT ã¬œ˙-flÌ6’¿¢/ü>Ìú]‘Td;n¯e¸Ò∞ˆ L%‰åqÀ*!é, òdB±≥=Ic™Û®ÇÛpÙ©ÁªÆ≥ŸA∏≥=˚≈8ŸûÑ—©›W_v˛Á_’Z•]˘W€$Ó‹˛˚fl_∆9û“å3€/Ûòbº)œ4…8KΩØõÚî>äÀË≈Ÿ˛Ít\ÿ›Í¯˝ß{ƒy∆7hÙt_=›ÄC$·Ä3åürƒâtgˆúASuúÅ£ªwnοlç_'èo—ä•"ÙîAÇ)–ÆÔ{˜ v£ÿuÔ∫”õL2Ãf«œæ√„Ô™NÙ¯ºb{∂\Ÿ”{MSLnfGÍ,h˛ù„ufÚ}ØÃˇ<Mú≥·áëÌV˝ÓL&åuKJÿBhöy&Ÿ∏䲖ãǵ<o=UpÊ˚8«@ÎEKwŒl˝Œ-∞Ë¥O›4õÓ”N√~ÏÎ~Ø∫ T∑ÌË€aàx   ¡$mƒ 
    ...
    --MIMEBoundaryurn_uuid_AF2837F4196B2631EC15070889135182607126--
    

    显然,我可以看到这里有zip数据。但我读了其他每一个回复 Hash.from_xml 显然这在这里行不通。

    Update test.zip

    Archive:  test.zip
    warning [test.zip]:  822 extra bytes at beginning or within zipfile
      (attempting to process anyway)
      inflating: 6509805153_report.xml   
    

    不确定它抱怨的额外字节是什么。

    Update 2 这绝对是MIME头和XML信封。我可以确认,如果我手动删除这些字符和MIME页脚,那么测试文件将在没有警告的情况下解压。

    因此,这似乎是一个包含zip文件的压缩XML信封。

    1 回复  |  直到 8 年前
        1
  •  1
  •   Derek Wright    8 年前

    这可能比仅仅使用库要复杂一些。我能找到的最接近的是savon SOAP库中的一个实现,它在多部分响应中处理xop。您可能能够分析那里的代码,并提出一个适合您需要的解决方案,或者如果这是一个SOAP服务,请利用savon gem。

    https://github.com/savonrb/savon-multipart/blob/master/lib/savon/multipart/response.rb#L63-L80