压缩存储在S3上的所有Paperclip附件

Paperclip是Rails的一个很棒的上传插件。 将上传存储在本地文件系统或Amazon S3上似乎运行良好。 我只假设本地主机上存储文件,但此应用程序需要使用S3,因为它将托管在Heroku上。

如何通过单个压缩下载从S3获取所有上传/附件?

本地文件系统获取zip 文件似乎很简单。 它让S3中的文件让我感到困惑。 我认为这可能与rubyzip处理URL引用的文件的方式有关。 我尝试了各种方法但似乎无法避免错误。

format.zip { registrations_with_attachments = Registration.find_by_sql('SELECT * FROM registrations WHERE abstract_file_name NOT LIKE ""') headers['Cache-Control'] = 'no-cache' tmp_filename = "#{RAILS_ROOT}/tmp/tmp_zip_" << Time.now.to_f.to_s < No such file or directory - http://s3.amazonaws.com/bucket/original/abstract.txt # Should note that these files in S3 bucket are publicly accessible. No ACL. # works with local storage. Thanks to Henrik Nyh # registrations_with_attachments.each { |e| zip.add("abstracts/#{e.abstract.original_filename}", e.abstract.path(:original)) } end send_data(File.open(tmp_filename, "rb+").read, :type => 'application/zip', :disposition => 'attachment', :filename => tmp_filename.to_s) File.delete tmp_filename } 

你几乎肯定想使用e.abstract.to_file.path而不是e.abstract.url(...)

看到:

  • Paperclip :: Storage :: S3 :: to_file (应该返回一个TempFile
  • 临时文件路径::

UPDATE

来自更改日志 :

3.0.1中的新function:

  • API CHANGE: #to_file已被删除。 请改用#copy_to_local_file方法。

@ vlard的解决方案还可以。 但是我遇到了to_file一些问题。 它创建一个临时文件,垃圾收集器在将文件添加到zip文件之前删除(有时)该文件。 因此,我得到随机的Errno::ENOENT: No such file or directory错误。

所以我现在使用以下代码(我保留了初始代码变量名称以与初始问题保持一致)

 format.zip { registrations_with_attachments = Registration.find_by_sql('SELECT * FROM registrations WHERE abstract_file_name NOT LIKE ""') headers['Cache-Control'] = 'no-cache' #please note that using nanoseconds option in strftime reduces the risks concerning the situation where 2 or more users initiate the download in the same time tmp_filename = "#{RAILS_ROOT}/tmp/tmp_zip_" << Time.now.strftime('%Y-%m-%d-%H%M%S-%N').to_s << ".zip" # rubyzip gem version 0.9.4 zip = Zip::ZipFile.open(tmp_filename, Zip::ZipFile::CREATE) zip.close registrations_with_attachments.each { |e| file_to_add = e.file.to_file zip = Zip::ZipFile.open(tmp_filename) zip.add("abstracts/#{e.abstract.original_filename}", file_to_add.path) zip.close puts "added #{file_to_add.path} to #{tmp_filename}" #force garbage collector to keep the file_to_add until after the file has been added to zip } send_data(File.open(tmp_filename, "rb+").read, :type => 'application/zip', :disposition => 'attachment', :filename => tmp_filename.to_s) File.delete tmp_filename }