Question

I have a zip archive in a string, but the rubyzip gem appears to want input from a file. The best I've come up with is to write the zip archive to a tempfile for the sole purpose of passing the filename to Zip::ZipFile.foreach(), but this seems tortured:

require 'zip/zip'
def unzip(page)
  "".tap do |str|
    Tempfile.open("unzip") do |tmpfile|
      tmpfile.write(page)
      Zip::ZipFile.foreach(tmpfile.path()) do |zip_entry|
        zip_entry.get_input_stream {|io| str << io.read}
      end
    end
  end
end

Is there a simpler way?

NOTE: See also Ruby Unzip String.

Was it helpful?

Solution

See Zip/Ruby Zip::Archive.open_buffer(...):

require 'zipruby'
Zip::Archive.open_buffer(str) do |archive|
  archive.each do |entry|
    entry.name
    entry.read
  end
end

OTHER TIPS

@maerics's answer introduced me to the zipruby gem (not to be confused with the rubyzip gem). It works well. My complete code ended up like this:

require 'zipruby'

# Given a string in zip format, return a hash where 
# each key is an zip archive entry name and  each
# value is the un-zipped contents of the entry
def unzip(zipfile)
  {}.tap do |entries|
    Zip::Archive.open_buffer(zipfile) do |archive|
      archive.each do |entry|
        entries[entry.name] = entry.read
      end
    end
  end
end

Ruby's StringIO would help in this case.

Think of it as a string/buffer you can treat like an in-memory file.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top