Ruby: 下载 zip 文件并解压
Ruby: Download zip file and extract
我有一个 ruby 脚本,它使用 rubys open
命令从服务器下载远程 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) 及其 class 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
我的问题是:
- 一般来说,是否可以下载 ZIP 文件并在内存中提取其内容?
- Rubyzip 是适合它的库吗?
- 如果是,我该如何提取内容?
我自己找到了解决方案,然后在 Whosebug :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
- 下载你的 ZIP 文件,我为此使用 HTTParty(但你也可以使用 ruby 的
open
命令(require 'open-uri'
)。
- 使用
StringIO.new(input)
将其转换为 StringIO
流
- 使用
io.get_next_entry
迭代 ZIP 存档中的每个条目(它 returns Entry
的一个实例)
io.read
获取内容,entry.name
获取文件名。
就像我在 中评论的那样,我们可以只使用 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
我有一个 ruby 脚本,它使用 rubys open
命令从服务器下载远程 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) 及其 class 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
我的问题是:
- 一般来说,是否可以下载 ZIP 文件并在内存中提取其内容?
- Rubyzip 是适合它的库吗?
- 如果是,我该如何提取内容?
我自己找到了解决方案,然后在 Whosebug :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
- 下载你的 ZIP 文件,我为此使用 HTTParty(但你也可以使用 ruby 的
open
命令(require 'open-uri'
)。 - 使用
StringIO.new(input)
将其转换为 - 使用
io.get_next_entry
迭代 ZIP 存档中的每个条目(它 returnsEntry
的一个实例) io.read
获取内容,entry.name
获取文件名。
StringIO
流
就像我在 中评论的那样,我们可以只使用 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