被上传到S3与CarrierWave的下载和压缩和解文件 [英] Downloading and zipping files that were uploaded to S3 with CarrierWave

查看:580
本文介绍了被上传到S3与CarrierWave的下载和压缩和解文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个小的Rails 3.2.1应用程序,使用CarrierWave 0.5.8文件上传到S3(使用雾)

I have a small Rails 3.2.1 app that uses CarrierWave 0.5.8 for file uploads to S3 (using Fog)

我希望用户能够选择一些他们想要下载的图像,然后压缩他们,并给他们一个zip。以下是我想出来的:

I want users to be able to select some images that they'd like to download, then zip them up and send them a zip. Here is what I've come up with:

def generate_zip
  #A collection of Photo objects. The Photo object has a PhotoUploader mounted.
  photos = Photo.all

  tmp_filename = "#{Rails.root}/tmp/" << Time.now.strftime('%Y-%m-%d-%H%M%S-%N').to_s << ".zip"
  zip = Zip::ZipFile.open(tmp_filename, Zip::ZipFile::CREATE)
  zip.close

  photos.each do |photo|
    file_to_add = photo.photo.file
    zip = Zip::ZipFile.open(tmp_filename)
    zip.add("tmp/", file_to_add.path)
    zip.close
  end

  #do the rest.. like send zip or upload file and e-mail link

end

这不起作用,因为photo.photo.file返回CarrierWave ::存储::雾::文件,而不是一个常规文件的一个实例。

This doesn't work because photo.photo.file returns an instance of CarrierWave::Storage::Fog::File instead of a regular file.

编辑:错误这会导致:

变量Errno :: ENOENT:没有这样的文件或目录 - 上传/照片/ name.jpg

Errno::ENOENT: No such file or directory - uploads/photos/name.jpg

我也试过如下:

tmp_filename = "#{Rails.root}/tmp/" << Time.now.strftime('%Y-%m-%d-%H%M%S-%N').to_s << ".zip"
    zip = Zip::ZipFile.open(tmp_filename, Zip::ZipFile::CREATE)
    zip.close

    photos.each do |photo|
      processed_uri = URI.parse(URI.escape(URI.unescape(photo.photo.file.authenticated_url)).gsub("[", "%5B").gsub("]", "%5D"))
      file_to_add = CarrierWave::Uploader::Download::RemoteFile.new(processed_uri)
      zip = Zip::ZipFile.open(tmp_filename)
      zip.add("tmp/", file_to_add.path)
      zip.close
    end

但是,这给了我一个403的一些帮助将不胜AP preciated ..这可能不是那么难,我只是做错了™

But this gives me a 403. Some help would be greatly appreciated.. It probably is not that hard I'm just Doing it Wrong™

推荐答案

我已经成功地从@ff​​oeg

I've managed to solve the problem with help from @ffoeg

由@ffoeg提供的解决方案没有工作这么对我很好,因为我正在处理zip文件> 500 MB这引起了我的问题在Heroku上。我为此感动使用荏苒到后台进程 resque

The solution offered by @ffoeg didn't work quite so well for me since I was dealing with zip files > 500 MB which caused me problems on Heroku. I've therefor moved the zipping to a background process using resque:

应用/工人/ photo_zipper.rb:

require 'zip/zip'
require 'zip/zipfilesystem'
require 'open-uri'
class PhotoZipper
  @queue = :photozip_queue

  #I pass 
  def self.perform(id_of_object_with_images, id_of_user_to_be_notified)
    user_mail = User.where(:id => id_of_user_to_be_notified).pluck(:email)
    export = PhotoZipper.generate_zip(id_of_object_with_images, id_of_user_to_be_notified)

    Notifications.zip_ready(export.archive_url, user_mail).deliver
  end

    # Zipfile generator
  def self.generate_zip(id_of_object_with_images, id_of_user_to_be_notified)
    object = ObjectWithImages.find(id_of_object_with_images)
    photos = object.images
    # base temp dir
    temp_dir = Dir.mktmpdir
    # path for zip we are about to create, I find that ruby zip needs to write to a real file
    # This assumes the ObjectWithImages object has an attribute title which is a string.
    zip_path = File.join(temp_dir, "#{object.title}_#{Date.today.to_s}.zip")

    Zip::ZipOutputStream.open(zip_path) do |zos|
      photos.each do |photo|
        path = photo.photo.path
        zos.put_next_entry(path)
        zos.write photo.photo.file.read
      end
    end

    #Find the user that made the request
    user = User.find(id_of_user_to_be_notified)

    #Create an export object associated to the user
    export = user.exports.build

    #Associate the created zip to the export
    export.archive = File.open(zip_path)

    #Upload the archive
    export.save!

    #return the export object
    export
  ensure

    # clean up the tempdir now!
    FileUtils.rm_rf temp_dir if temp_dir
  end


end

应用程序/控制器/ photos_controller.rb:

  format.zip do
    #pick the last ObjectWithImages.. ofcourse you should include your own logic here
    id_of_object_with_images = ObjectWithImages.last.id

    #enqueue the Photozipper task
    Resque.enqueue(PhotoZipper, id_of_object_with_images, current_user.id)

    #don't keep the user waiting and flash a message with information about what's happening behind the scenes
    redirect_to some_path, :notice => "Your zip is being created, you will receive an e-mail once this process is complete"
  end

非常感谢@ffoeg帮助我。如果你的拉链是小,你可以尝试@ ffoeg的解决方案。

Many thanks to @ffoeg for helping me out. If your zips are smaller you could try @ffoeg's solution.

这篇关于被上传到S3与CarrierWave的下载和压缩和解文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆