3

我最近完成了 plupload 的设置,将文件直接上传到 S3。这是使用 S3s发布方法结合 plupload 完成的。

上传完成后,我将加载模型的延迟作业排队,并使用 CarrierWave 的 remote_[uploader]_url 方法将该上传的资源分配给模型。由于管理多个版本的简单性,我想使用 CarrierWave。这是我的工作(稍作编辑,我意识到我可以将 send_later 用于这个简单的示例):

class MediaJob < Struct.new(:medium)
  def perform
    medium.process_file
    medium.save
  end
end

这是 process_file 方法:

def process_file
  self.remote_file_url = s3_original_url
end

结果是文件最终进出 S3 3 次:

1)通过plupload上传到S3

2) 由 CarrierWave 下载进行处理

3) 模型保存时由 CarrierWave 重新上传

这对于小文件来说很好,但在处理大文件时会变得非常昂贵。一定有办法消除#3。我不希望 CarrierWave 在保存时上传原始文件,因为原始文件已经存在。我确实希望上传这些版本。

4

3 回答 3

4

So I have found a solution. Thanks to the contributors for getting it started. I want to make sure credit is given where it is due but the answer was a bit more involved than what was proposed.

Here is what worked....

1) After plupload finishes uploading to S3, I assigned the file attribute (my mounted CarrierWave uploader) to the returned key from S3. This is accomplished in plupload by using the FileUploaded event to post the response to another action:

init : {
    FileUploaded: function(up, file, info) {
        $.post('#{media_path}', {s3_response: info.response});
    }
}

2) The action picks up that response and assigns the file attribute(or whatever the name of your mounted uploader is) via a method on the model:

def create
  med = Medium.new_from_s3_response(params[:s3_response])
end

def self.new_from_s3_response(response)
  med = Medium.new

  # Grab filename from response use libxml-ruby gem
  xml = XML::Parser.string(response).parse
  node = xml.find_first('//PostResponse/Key')
  med['file'] = node.content
  med.save

  # Queue up a job to have the file downloaded and processed
  # Note that I am using Mongoid so the handy serialization by DelayedJob doesn't work
  Delayed::Job.enqueue MediaJob.new(med.id)
end

3) The job fires and calls process_file which downloads the original and creates/uploads the various versions. Note that the original does not get uploaded. Mission accomplished!

class MediaJob < Struct.new(:medium_id)
  def perform
    medium = Medium.find(medium_id)
    medium.process_file

  end
end  

def process_file
  # Download from S3
  file.cache_stored_file!
  # Convert to sanitized file for creating versions
  file.retrieve_from_cache!(file.cache_name)

  # Loop through versions and create them....
  file.versions.values.each do |uploader|
    uploader.store!
  end
end

I got the code for creating the versions from a wiki entry on the CarrierWave GitHub page.

于 2012-06-22T23:29:08.397 回答
2

如果你使用update_attribute它应该跳过回调。我不知道carrierwave在内部是如何工作的,但这就是我会尝试的:

def process_file
  update_attribute(:remote_file_url, s3_original_url)
end

然后,您可以跳过呼叫save

另一种方法是更改save​​为save(:validate => false).

编辑:您可以使用skip_callback跳过验证http://api.rubyonrails.org/classes/ActiveSupport/Callbacks/ClassMethods.html#method-i-skip_callback

于 2012-06-22T14:55:35.993 回答
0

也许您可以尝试类似的事情(我也为存储在 s3 中的 CSV 文件做了类似的事情)

1. Download the file to your local directory first 

2. Process the the image (create your version) 

3. And then Upload the file to s3 using fog gem separately 

4. update the remote_url  from the url from the fog gem 

这会将您的步骤从 3 减少到 1

您可以查看 Fog文档以获取 s3 url

希望这有帮助

于 2012-06-22T18:10:48.320 回答