In a Ruby on Rails application I'm developing, client asked me to add a feature that allows users to download a full picture gallery as a single zip file. Quite obviously, I decided to take advantage of rubyzip gem to create the compressed archive to download. But my idea was to create the zip on the fly, directly in memory, without fill folders of my application with many zip files that I need to remove later. Hence the idea of using Tempfile to create the file in memory. Here's the function I created: "download_zip".
def download_zip(image_list)
if !image_list.blank?
file_name = 'pictures.zip'
t = Tempfile.new('mio-file-temp-2016-02-19 10:41:53 +0100')
Zip::ZipOutputStream.open(t.path) do |z|
image_list.each do |img|
title = img.title
title += '.jpg' unless title.end_with?('.jpg')
z.put_next_entry(title)
z.print IO.read(img.path)
end
end
send_file t.path, :type => 'application/zip', :disposition => 'attachment', :filename => file_name
t.close
end
end
This is what the download_zip function does:
- takes as input a list of Image objects, where Image has at least the two properties: title and path.
- create a temporary file and open it as a ZipOutputStream.
- for each image in the list creates a new element in ZipOutputStream with the name equal to the image title and content is the image read from path.
- the close ofthe block Zip::ZipOutputStream ... end will cause the new file zip will be automatically closed.
- now, the file is sent to the user, with the right mime-type set.
- the last instruction close the temporary file that will be removed from memory later by the garbage collector.