/ filesInternetrailsuploads

attachment_fu s3 uploads with backgroundjob

Thanks to Jon Guymon for his article bj-makes-attachment_fu-happy that really help me solve a problem I was having with mongrel.

Attachment_fu + s3 sometimes do very weird things that makes mongrel to freeze. After a lot of googling I realize that the best solution to avoid problems was to do the uploads to S3 in a background proccess apart from mongrel.

I started with Jon Guymon approach and it worked well but i needed to create thumbnails and the local files to be deleted after the uploading to S3 was finished.

Just changing the part of attachment_fu that actually uploads the file to S3 do the trick.

Open vendor/plugins/attachment_fu/lib/technoweenie/attachment_fu/backends/s3_backend.rb and change the method save_to_storage to background the uploads.

This is the original method:

def save_to_storage if save_attachment? S3Object.store( full_filename, (temp_path ? File.open(temp_path) : temp_data), bucket_name, :content_type => content_type, :access => attachment_options[:s3_access] ) @old_filename = nil true end end

In my version I copy the file to a temporary directory in tmp/s3uploads (just to make sure the file does not disappear) then I add the upload task to the background queue

def save_to_storage if save_attachment? my_temp_file = RAILS_ROOT+'/tmp/s3uploading/'+"#{rand Time.now.to_i}#{filename || 'attachment'}"

if temp_path File.open(my_temp_file,"w+") do |tmp| tmp.close FileUtils.cp temp_path, tmp.path end else File.open(my_temp_file, "w+") do |tmp| tmp.binmode tmp.write temp_data tmp.close end fichero = RAILS_ROOT+'/tmp/s3uploading/' + "#{rand Time.now.to_i}#{filename || 'attachment'}" end

Bj.submit("./script/runner ./jobs/s3_uploader.rb " + full_filename + " " + my_temp_file + " " + bucket_name + " " + content_type + " " + attachment_options[:s3_access].to_s ) end

@old_filename = nil true end

This way attachment_fu will spawn a task for every file it creates.

Now edit the file Jon Guymon created to handle the upload (jobs/s3_uploader.rb)

This is how my file looks like

Base.establish_connection!(:access_key_id => ACCESS_KEY, :secret_access_key => SECRET_KEY)

S3Object.store(ARGV[0], File.open(ARGV[1]), ARGV[2], :content_type => ARGV[3], :access => ARGV[4] )

File.delete(ARGV[1])

A simple upload to S3 and after finishing it I delete the temporary file created in tmp/s3uploads/

So far mongrel is doing its job with no more hangs and as a side effect users can uploads their files faster.

There are a lot of pages about backgrounding tasks and a good recipe in Rails recipes 2