如何使用 Ruby 读取此二进制 XML 响应?
How can I read this binary XML response with Ruby?
我正在尝试读取来自市场 Web 服务的响应。来自此 Web 服务的所有其他响应都以 XML 格式返回。但是,此特定调用请求文件下载。我不熟悉它返回的方式。查看内容后,有 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
,我可以在 Linux 命令行解压缩它,并在闪烁此警告后创建一个可读的 XML 文件:
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 header 和 XML 信封。我可以确认,如果我手动删除这些字符和 MIME 页脚,那么测试文件会在没有警告的情况下解压缩。
所以这似乎是一个包含压缩文件的压缩 XML 信封。
这可能比仅仅使用库要复杂一些。我能找到的最接近的是 savon SOAP 库中的一个实现,它处理多部分响应中的 xop。您可能能够分析那里的代码并提出适合您需要的解决方案,或者如果这是 SOAP 服务,请利用 savon gem.
https://github.com/savonrb/savon-multipart/blob/master/lib/savon/multipart/response.rb#L63-L80
我正在尝试读取来自市场 Web 服务的响应。来自此 Web 服务的所有其他响应都以 XML 格式返回。但是,此特定调用请求文件下载。我不熟悉它返回的方式。查看内容后,有 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
,我可以在 Linux 命令行解压缩它,并在闪烁此警告后创建一个可读的 XML 文件:
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 header 和 XML 信封。我可以确认,如果我手动删除这些字符和 MIME 页脚,那么测试文件会在没有警告的情况下解压缩。
所以这似乎是一个包含压缩文件的压缩 XML 信封。
这可能比仅仅使用库要复杂一些。我能找到的最接近的是 savon SOAP 库中的一个实现,它处理多部分响应中的 xop。您可能能够分析那里的代码并提出适合您需要的解决方案,或者如果这是 SOAP 服务,请利用 savon gem.
https://github.com/savonrb/savon-multipart/blob/master/lib/savon/multipart/response.rb#L63-L80