Using Rails with Paperclip and Swfupload

swfupload + paperclip + rails 3

I made two apps here: https://github.com/apneadiving/Pic-upload---Crop-in-Ajax

  • with jQuery upload

  • with swfupload

They could be good examples

Rails: Paperclip & previews?

This kind of thing is problematic from a Rails perspective because of the way image uploads work. One strategy to make it work better is:

  • Make a sub-form for your image upload, possibly using swfupload to make it more streamlined.
  • Create a model to receive your uploads that includes some randomized access key used to retrieve and link it. Paperclip handles the attached file.
  • Use AJAX to populate your main form by inserting a hidden field, or potentially a visible check-box element with the appropriate unique_key, when the subform finishes.

A typical model looks something like this:

class Avatar < ActiveRecord::Base
has_attached_file :image
# ... Additional Paperclip options here

before_validation :assign_unique_key

belongs_to :user

def to_param
self.unique_key
end

protected
def assign_unique_key
return if (self.unique_key.present?)

self.unique_key = Digest::SHA1.hexdigest(ActiveSupport::SecureRandom.random_number(1<<512).to_s)
end
end

The reason for the unique_key field is so that you can link this in to the form of a potentially unsaved record. It is advantageous to use the unique_key instead of id when putting it in URLs since it is hard to tell if a user should be able to see this picture or not when it is uploaded since the owner user may not yet be assigned.

This also prevents curious people from altering some kind of sequential, easily guessable ID in your URL and seeing other avatars that have been uploaded.

You can retrieve the final resized thumbnail URL for the Avatar as you would any model at this point.

You can easily strip out the parameters on receipt and translate back to Avatar ID numbers:

# If an avatar_id parameter has been assigned...
if (params[:user][:avatar_id])
# ...resolve this as if it were a unique_key value...
avatar = Avatar.find_by_unique_key(params[:user][:avatar_id])
# ...and repopulate the parameters if it has been found.
params[:user][:avatar_id] = (avatar && avatar.id)
end

# ... params[:user] used as required for create or update

As people upload and re-upload images, you will eventually have a large number of orphaned records that are not actually used anywhere. It is simple to write a rake task to purge all of these after a reasonable amount of time has passed. For example:

task :purge_orphan_avatars => :environment do
# Clear out any Avatar records that have not been assigned to a particular
# user within the span of two days.
Avatar.destroy_all([ 'created_at<? AND user_id IS NULL', 2.days.ago ])
end

Using destroy_all should have the effect of purging all Paperclip material as well.

Rails Paperclip and AJAX form

You can't upload a file with AJAX. It's probably the reason why the submit is in HTML and not in JS.

Nevertheless you have some hack to solve this problem:

  • HTML5: http://www.queness.com/post/11434/7-javascript-ajax-file-upload-plugins
  • Flash: http://code.google.com/p/swfupload/
  • iframe method: http://www.google.com/search?q=ajax%2Biframe%2Bupload

I hope this help

How to get image capture date and video duration when uploading files using SWFUpload and Paperclip on Rails

It turns out that SWFUpload provides access to the file properties before uploading in the handlers.js file. So, to get the capture date:

//handlers.js    
function uploadStart(file) {
// set the captured_at to the params
swfu.removePostParam("captured_at");
swfu.addPostParam("captured_at", file.modificationdate);
...
}

Now, you can receive it in the controller:

class UploadsController < ApplicationController
def create
@upload.captured_at = params[:captured_at].try :to_time
...
end
end

To get the video duration, we have used Paperclip's before_post_process to run an FFmpeg command:

class Upload < ActiveRecord::Base
before_post_process :get_video_duration

def get_video_duration
result = `ffmpeg -i #{self.media.to_file.path} 2>&1`
if result =~ /Duration: ([\d][\d]:[\d][\d]:[\d][\d].[\d]+)/
self.duration = $1.to_s
end
return true
end
...
end

Paperclip Progress bar

I think I have found an answer.
http://github.com/pkordel/uploadify_paperclip_demo

This seems to be a working and easy to implement.

Rails 2.3.10, Paperclip and s3 dead slow and would like to Ajax

There are a couple of popular javascript upload handlers which will display upload progress and can resize the original image prior to upload. Plupload and swfupload. Looking for a swfupload url their site is down so maybe plupload is a better bet.

You should still use delayed job as it means the user doesn't need to wait for your server to reprocess the image on s3, after their internet connection has sent it to your server. It's very simple to set up, in fact, there's a delayed_paperclip plugin which handles it all for you.

edit:

Here's a couple of gems that should make swfupload installation easier.

swfupload rails 2 gem

swfupload rails 3 gem

Also a good tutorial on flash upload with session. Be sure to read updates toward end.



Related Topics



Leave a reply



Submit