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 <<
".zip"
# rubyzip gem version 0.9.1
# rdoc http://rubyzip.sourceforge.net/
Zip::ZipFile.open(tmp_filename, Zip::ZipFile::CREATE) do |zip|
#get all of the attachments
# attempt to get files stored on S3
# FAIL
registrations_with_attachments.each { |e| zip.add("abstracts/#{e.abstract.original_filename}", e.abstract.url(:original, false)) }
# => 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
}
答案 0 :(得分:11)
您几乎肯定希望使用e.abstract.to_file.path
代替e.abstract.url(...)
。
请参阅:
TempFile
)来自changelog:
3.0.1中的新内容:
- API更改:
#to_file
已被删除。请改用#copy_to_local_file
方法。
答案 1 :(得分:2)
@ 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
}