Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Tempfile to create a zip file in rails

I want to create a temporary .zip in rails. For creating zip file I am using rubyzip gem.

Currently I am doing this:

zfname = Tempfile.new(['somename','.zip'], Rails.root.to_s + '/tmp/')
Zip::ZipFile.open(zfname.path, Zip::ZipFile::CREATE) do |zipfile|
  zipfile.add(file, basepath + file)
end

This generates following error:

Zip::ZipError: Zip end of central directory signature not found

Is it possible to use Tempfile for zip? If yes, what is wrong here?

like image 887
shivam Avatar asked Dec 20 '14 06:12

shivam


People also ask

How do I create a zip file from a project?

Right-click on the file or folder.Select “Compressed (zipped) folder”. To place multiple files into a zip folder, select all of the files while hitting the Ctrl button. Then, right-click on one of the files, move your cursor over the “Send to” option and select “Compressed (zipped) folder”.

How do I use Zipfile?

To zip (compress) a file or folder Locate the file or folder that you want to zip. Press and hold (or right-click) the file or folder, select (or point to) Send to, and then select Compressed (zipped) folder. A new zipped folder with the same name is created in the same location.

What is Rubyzip?

Rubyzip is a ruby library for reading and writing zip files.

What is Python Zipfile?

Python's zipfile is a standard library module intended to manipulate ZIP files. This file format is a widely adopted industry standard when it comes to archiving and compressing digital data. You can use it to package together several related files.


2 Answers

In my rails app when I needed to send zip files to user, I just stored them in a buffer and used 'send data' method in controller. I was trying to use 'Tempfile' initially but it had an added task of removing zip files after sending it to user which is a pain. Is this something you are looking for?

    Zip::OutputStream.write_buffer do |stream|
      file_paths.each_with_index do |file_path, index|
        # rename the pdf
        stream.put_next_entry("#{name}-#{index + 1}.pdf")
        # add pdf to zip
        stream.write IO.read(file_path)
      end  
    end
like image 110
Aditya Shedge Avatar answered Oct 17 '22 00:10

Aditya Shedge


So it doesn't actually look like you need or want a Tempfile. You really want a random path in the Rails.root/tmp directory. Try something like this:

zfpath = Rails.root.join('tmp', "somename-#{SecureRandom.hex(8)}.zip"
Zip::ZipFile.open(zfpath, Zip::ZipFile::CREATE) do |zipfile|
  zipfile.add(file, basepath + file)
end

Update:

While it's far more complex, you can find a discussion of how to do this with a Tempfile here - http://thinkingeek.com/2013/11/15/create-temporary-zip-file-send-response-rails/ .

like image 36
Peter Goldstein Avatar answered Oct 17 '22 00:10

Peter Goldstein