【问题标题】:Ruby: Download zip file and extractRuby:下载 zip 文件并解压
【发布时间】:2016-01-15 08:54:24
【问题描述】:

我有一个 ruby​​ 脚本,它使用 ruby​​s opencommand 从服务器下载远程 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\x00@\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 gem (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. 如果是,如何提取内容?

【问题讨论】:

    标签: ruby zip rubyzip


    【解决方案1】:

    我自己找到了解决方案,然后在 stackoverflow :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) 将其转换为StringIO
    3. 使用 io.get_next_entry 遍历 ZIP 存档中的每个条目(它返回 Entry 的实例)
    4. io.read 获取内容,entry.name 获取文件名。

    【讨论】:

    • 我在上面尝试了相同的代码,但对我不起作用,我看到这个错误:rubyzip-0.9.9/lib/zip/zip_input_stream.rb:52:in initialize': can't convert StringIO into String (TypeError)`
    • 我正在使用rubyzip 1.1.7,所以也许这就是问题所在?您是否从上面复制并粘贴了我的代码?错误发生在哪一行(在您的代码中)?
    • 是的,原来我访问的远程 zip 已损坏。现在一切都好。谢谢。
    【解决方案2】:

    就像我在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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-03-07
      • 1970-01-01
      • 2021-11-23
      • 1970-01-01
      • 2011-05-28
      • 2021-03-03
      • 2023-03-22
      • 1970-01-01
      相关资源
      最近更新 更多