Question

How can I generate zip file without saving to the disk with Ruby?

I have generated many PDF files in memory and I want to compress them into one zip file before sending it as a email attachment. I have looked at Rubyzip and it does not allows me to create a zip file without saving it to disk (maybe I am wrong).

Is there any way I can compress those file without creating a temp file?

 45  18212  45
1 Jan 1970

Solution

 64

I had a similar problem which I solved using the rubyzip gem and the stringio object. It turns out that rubyzip provides a method that returns a stringio object: ZipOutputStream.write_buffer.

You can create the zip file structure as you like using put_next_entry and write and once you are finished you can rewind the stringio and read the binary data using sysread.

See the following simple example (works for rubyzip 0.9.X)

require 'zip/zip'
stringio = Zip::OutputStream.write_buffer do |zio|
  zio.put_next_entry("test.txt")
  zio.write "Hello world!"
end
stringio.rewind
binary_data = stringio.sysread

Tested on jruby 1.6.5.1 (ruby-1.9.2-p136) (2011-12-27 1bf37c2) (Java HotSpot(TM) 64-Bit Server VM 1.6.0_29) [Windows Server 2008-amd64-java])

The following example works for rubyzip >= 1.0.0

require 'rubygems'    
require 'zip'
stringio = Zip::OutputStream.write_buffer do |zio|
  zio.put_next_entry("test.txt")
  zio.write "Hello world!"
end
binary_data = stringio.string

Tested on jruby 1.7.22 (1.9.3p551) 2015-08-20 c28f492 on OpenJDK 64-Bit Server VM 1.7.0_79-b14 +jit [linux-amd64] and rubyzip gem 1.1.7

2012-03-15

Solution

 5

Ruby comes with a very convenient StringIO library - this can be used for using a String as output IO object or faking reading a file backed by a String.

The challenge here is that RubyZip does not support directly taking an IO object when creating a Zip::ZipOutputStream, but if you look at the implementation of the initialize, and depending on your willingness to experiment, you may be able to extend the class and allow it to take either an IO object or a file name in the constructor.

2010-04-12