2015-10-16 102 views
4

我有一個ruby腳本,它使用rubys open命令從服務器下載遠程ZIP文件。當我看着下載的內容,它顯示了這樣的事情:Ruby:下載zip文件並提取

PK\x03\x04\x14\x00\b\x00\b\x00\x9B\x84PG\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\n\x00\x10\x00foobar.txtUX\f\x00\x86\v!V\x85\v!V\xF6\x01\x14\x00K\xCB\xCFOJ,RH\x03S\\\x00PK\a\b\xC1\xC0\x1F\xE8\f\x00\x00\x00\x0E\x00\x00\x00PK\x01\x02\x15\x03\x14\x00\b\x00\b\x00\x9B\x84PG\xC1\xC0\x1F\xE8\f\x00\x00\x00\x0E\x00\x00\x00\n\x00\f\x00\x00\x00\x00\x00\x00\x00\[email protected]\xA4\x81\x00\x00\x00\x00foobar.txtUX\b\x00\x86\v!V\x85\v!VPK\x05\x06\x00\x00\x00\x00\x01\x00\x01\x00D\x00\x00\x00T\x00\x00\x00\x00\x00 

我使用Rubyzip寶石(https://github.com/rubyzip/rubyzip)及其Zip::ZipInputStream類一起這樣的嘗試:

stream = open("http://localhost:3000/foobar.zip").read # this outputs the zip content from above 
zip = Zip::ZipInputStream.new stream 

不幸的是,這將引發錯誤:

Failure/Error: zip = Zip::ZipInputStream.new stream 
ArgumentError: 
    string contains null byte 

我的問題是:

  1. 一般來說,是否可以下載ZIP文件並將其內容提取到內存中?
  2. Rubyzip是正確的庫嗎?
  3. 如果是這樣,我該如何提取內容?

回答

5

我找到了解決辦法我自己,然後在計算器:d(How to iterate through an in-memory zip file in Ruby

input = HTTParty.get("http://example.com/somedata.zip").body 
Zip::InputStream.open(StringIO.new(input)) do |io| 
    while entry = io.get_next_entry 
    puts entry.name 
    parse_zip_content io.read 
    end 
end 
  1. 下載您的ZIP文件,我使用HTTParty這個(但你也可以使用Ruby的open命令(require 'open-uri')。
  2. 轉換成使用StringIO.new(input)
  3. 遍歷ZIP檔案館內的每個條目的StringIO流e使用io.get_next_entry(它返回Entry的一個實例)
  4. 使用io.read可以獲得內容,使用entry.name可以獲得文件名。
+0

我想這相同的代碼之上,但對我不起作用,我看到這個錯誤:'rubyzip-0.9.9/lib/zip/zip_input_stream.rb:52:在'initialize'中:無法將StringIO轉換爲字符串(TypeError)' – Kush

+0

我正在使用'rubyzip'' 1.1.7',所以也許這就是問題所在?你是否從上面複製並粘貼了我的代碼?在哪一行(在你的代碼中)發生錯誤? – 23tux

+0

是的,事實證明,我正在訪問的遠程zip已損壞。現在都好。謝謝。 – Kush

1

就像我在https://stackoverflow.com/a/43303222/4196440評論,我們可以只使用Zip::File.open_buffer

require 'open-uri' 

content = open('http://localhost:3000/foobar.zip') 

Zip::File.open_buffer(content) do |zip| 
    zip.each do |entry| 
    puts entry.name 
    # Do whatever you want with the content files. 
    end 
end