require 'zip'

module DC

  # Helper methods for dealing with packaging zip archives, for mixing in to
  # controllers.
  module ZipUtils

    def package(zip_name)
      temp_dir = Dir.mktmpdir# do |temp_dir|
        zipfile = "#{temp_dir}/#{zip_name}"
        Zip::File.open(zipfile, Zip::File::CREATE) do |zip|
          yield zip
        end
        # TODO: We can stream, or even better, use X-Accel-Redirect, if we can
        # be sure to clean up the Zip after the fact -- with a cron or equivalent.
        send_file zipfile, :stream => false
#      end
    end

  end

end

require 'zip'

module DC

  # Helper methods for dealing with packaging zip archives, for mixing in to
  # controllers.
  module ZipUtils

    def package(zip_name)
      zipfile = Tempfile.new(["dc",".zip"])
      Zip::File.open(zipfile.path, Zip::File::CREATE) do |zip|
        yield zip
      end
      send_file zipfile.path, :type => 'application/zip', :disposition => 'attachment', :filename => zip_name
      zipfile.close
    end

  end

end

Use Tempfile for zipfile creation
Use Tempfile for zipfile creation

When Dir.mktmpdir is unlinked, the inner files are inaccessible to send_file.
This meant that we had to keep it around until after the download was complete,
which littered the /tmp directory with directories filled with zip files.

Since we only need a single file, Tempfile is more appropriate.  We can close
the filehandle and any process that is currently reading from it (like send_file)
can continue to read even after the file is unlinked when the tempfile is
garbage collected.

A future enhancement might be to switch to the Zipline gem.  That would allow
streaming the zip file while files are being added to it, allowing downloading
to begin sooner.
