我最近设置了plupload来直接将文件上传到S3。这是使用S3s posting方法结合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三次:
1)使用plupload上传到S3
2)由CarrierWave下载以进行处理
3)保存模型时由CarrierWave重新上传
对于小文件来说,这一切都很好,但在处理较大的文件时却非常昂贵。必须有一种消除#3的方法。我不希望CarrierWave在保存时上传原始文件,因为原始文件已存在。我确实希望上传版本。
答案 0 :(得分:4)
所以我找到了解决方案。感谢贡献者的开始。我想确保给予应有的信用,但答案比提议的要多得多。
这是有用的......
1)在plupload完成上传到S3之后,我将文件属性(我安装的CarrierWave上传器)分配给S3的返回键。这是通过使用FileUploaded事件将响应发布到另一个操作而在plupload中完成的:
init : {
FileUploaded: function(up, file, info) {
$.post('#{media_path}', {s3_response: info.response});
}
}
2)该操作选择该响应,并通过模型上的方法分配文件属性(或任何已安装的上传者的名称):
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)作业触发并调用process_file,下载原始文件并创建/上传各种版本。请注意,原始文件未上传。任务完成了!
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
我从CarrierWave GitHub页面的wiki条目中获得了创建版本的代码。
答案 1 :(得分:2)
如果您使用update_attribute
,则应跳过回调。我不知道载波如何在内部工作,但这就是我想要的:
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
答案 2 :(得分:0)
Perhap您可以尝试类似的东西(我也为存储在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 documentation以获取s3网址
希望这个帮助