SWFUpload, Paperclip and Ruby on Rails

May 15th, 2008

Edit: Added paperclip validations to photo model. Fixed a bug with the js (thanks to Kevin). Commented the js file and added all methods used by SWFUPload.

SWFUpload

SWFUpload is a small JavaScript/Flash library to get the best of both worlds. It features the great upload capabilities of Flash and the accessibility and ease of HTML/CSS.

SWFUpload is a brilliant tool built with flash and javascript that allows you to upload multiple files at the same time, allows you to display progress bars and various other useful things. The front end is left wide open by the SWFUpload API so it gives you complete control over how the UI works.

Paperclip

As many of you might have realised, I love Paperclip. It’s a great plugin that takes care of all the grunt work and lets you get on with other stuff. I’ve covered how to use Paperclip before.

Making Rails Play Nice with SWFUpload

There are a couple of pitfalls when using SWFUpload with your projects. I’ve covered them below:

Scrambled Mime Types

This is an annoying problem caused by the upload facility in Flash. It basically means that all the files you upload via SWFUpload have the content type of application/octet-stream, which in most cases isn’t what you want.

To fix this you will want to use the Mime-Types gem. To Install, simply do the following:

gem install mime-types

Now that you’ve got the mime types gem installed remember to require it somewhere in your code:

require 'mime/types'

The way I’ve used it in the test project at the bottom is instead of assigning files to a model via @photo.file = params[:photo][:file], I’ve created a custom method that fixes the mime type then passes the file to the correct method.

# Fix the mime types. Make sure to require the mime-types gem
def swfupload_file=(data)
  data.content_type = MIME::Types.type_for(data.original_filename).to_s
  self.file = data
end

This takes care of the first problem.

Problems with Sessions

Flash has problems dealing with Rails sessions so a couple of quick fixes are needed. The first is to hack the sessions class. The fix can be found here.

I’ve included that code into a file called swfupload_fix.rb and placed it inside my initializers folder, so it’s loaded by the app is started.

Next add the following to your controller that handles the uploads:

session :cookie_only => false, :only => :create
The Controller

By default, SWFUpload passes the post variable of Filedata when uploading. This can be changed easily if needed. The way I’ve dealt with the uploading in the test application is as follows:

def create
  # SWFUpload file
  if params[:Filedata]
    @photo = Photo.new(:swfupload_file => params[:Filedata])
    if @photo.save
      render :partial => ‘photo’, :object => @photo
    else
      render :text => “error”
    end
  else
    # Standard upload
    @photo = Photo.new params[:photo]
    if @photo.save
      flash[:notice] = ‘Your photo has been uploaded!’
      redirect_to photos_path
    else
      render :action => :new
    end
  end
end

There’s probably a better way to do it, but for an example it shows you to logics of everything.

Linux and Flash Upload Progress

As Tim mentions in the comments there is a problem with displaying upload progress in Flash for Linux. It is covered around the net and alos mentioned in the documentation for SWFUpload:

The uploadProgress event is fired periodically by the Flash Control. This event is useful for providing UI updates on the page.

Note: The Linux Flash Player fires a single uploadProgress event after the entire file has been uploaded. This is a bug in the Linux Flash Player that we cannot work around.

So basically it’s boned on linux and there’s nothing you can do about it.

SWFUpload and Paperclip App

Hopefully, this should get you on your way to using SWFUpload with Paperclip in Rails. However, I’ve created a small app that should help you on your way to getting things working. If you have any problems or find any thing that could be done better, let me know and I’ll fix them up.

It has been tested on Firefox 2.0, Safari 3.1.1 and IE 7 on Windoze Vista. Not tested on IE 6 because, quite frankly, it can fuck right off.

To try the app: unzip the file, change to the swfupload directory then run the following:

rake db:migrate
ruby script/server

Then you should be able to see it by visiting http://localhost:3000.

SWFUpload Test Project

A test project to show how to get Ruby on Rails, SWFUpload and Paperclip to play together nicely.

You can also grab the example application from github:

git://github.com/JimNeath/swfupload---paperclip-example-app.git

Credit Where Credits Due

A lot of places helped be get my head around this stuff. So A massive thanks to Andy Stewart over at Air Blade Software and Dylan Vaughn.

More Resources

(Possibly) Related Posts

You can follow any responses to this entry through the RSS 2.0 feed. Trackback from your own site.

40 Responses to “SWFUpload, Paperclip and Ruby on Rails”

  1. May 15th, 2008 at 4:24 pm - coxy Says:

    Thanks… just what I’ve been looking for.

    Just wondering how this fairs against FancyUpload (http://digitarald.de/project/fancyupload/) in terms of ease-of-use.. ever used it?


  2. May 15th, 2008 at 4:27 pm - Tim Says:

    Hi Jim,

    Downloaded your sample project, installed the gem, ran the migration, and I am able to upload a file normally, but the swfupload always just hangs. no errors in server log, no messages anywhere. it shows the image, and and ” uploading…”, but the progress bar never moves. Upload normally on the other hand works just fine. Any ideas what might be missing?


  3. May 15th, 2008 at 4:54 pm - Jim Neath Says:

    @coxy - I’ve never actually used FancyUpload. It used flash (from what I’ve read) so I assume the same problems (and solutions) will apply.

    @Tim - Is it just the progress bar that doesn’t move? Does the image replace the content of the div with the details in? I’ve got a feeling that it’s something to do with the way I’ve implemented the progress code. Are you running OS X and FF? Because that’s what I’ve had problems on before.


  4. May 15th, 2008 at 5:08 pm - masch Says:

    Hi! Tim
    I downloaded and run the test, but when i try to upload a file in java script mode i got this error:
    MASSIVE ERROR!!!1
    Do you know how to fixed?

    Salu2…


  5. May 15th, 2008 at 6:40 pm - Nate Leavitt Says:

    Hi Jim,

    Thanks for the article! I am having some issues with the thumbnails being created. I have ImageMagik installed… hmm.


  6. May 15th, 2008 at 8:16 pm - Fannar Says:

    Doesn’t work in Safari on Mac.

    Works fine in Firefox.


  7. May 15th, 2008 at 9:26 pm - Kevin Says:

    Good write up. Bizarrely (given your comment), I can only get the example to run in FF (3.0 b5) under OSX. Safari gives the following errors..

    SyntaxError: Parse error
    http://localhost:3000/javascripts/upload.js?1210847188 (line 16)

    Can’t find variable: Upload http://localhost:3000/ (line 76)


  8. May 15th, 2008 at 9:45 pm - Kevin Says:

    The fix seems to be to quote the word ‘class’ in line 16 or upload.js,

    div = $(”).attr({ id: file.id,’class’: ‘photo’});

    now works in Safari on OSX.


  9. May 15th, 2008 at 9:47 pm - Kevin Says:

    oops that line got mangled..


  10. May 16th, 2008 at 1:15 am - omarvelous Says:

    I was just on your website yesturday, after googling to find a solution to integrate SWF and Paperclip…. I see I was only a day late! Ur the man!! Bookmarked!


  11. May 16th, 2008 at 3:20 am - omarvelous Says:

    I too am experience freezing with the multi upload feature. Using XP, and FF 2…

    Will try with IE and Safari soon.


  12. May 16th, 2008 at 3:22 am - omarvelous Says:

    Whoops…. I take that back… I see I had to press the button once more…. I wonder if that could be changed? Change it to automatically begin uploading as soon as they are selected.


  13. May 16th, 2008 at 5:33 am - links for 2008-05-16 at Topper’s Blog Says:

    [...] SWFUpload, Paperclip and Ruby on Rails | Javascript (tags: upload website rails paperclip swfupload swf flash easy multi) [...]


  14. May 16th, 2008 at 9:18 am - Jim Neath Says:

    @Masch - Check what error messages you’re getting from mongrel/webrick. The massive error message is just a sample of how to handle the error handling. It means something has gone on the server side.

    @Nate Leavitt - It should work with ImageMagick. What problems are you having?

    @Kevin - Thanks for the fix. I’ll update the source. Still not had change to test on my mac yet, but will get issues sorted when I get chance.

    @omarvelous - You should just be able to select your images with the browse button and then upload with the upload button. I did it this way so people could see how the browse/upload buttons could work.

    I’ll add fixes and look into the other issues today. It was just a quick example I knocked up yesterday to show to do uploads with paperclip/swfupload.

    Would anyone be interested in me putting this up on github so people can add their own patches?


  15. May 16th, 2008 at 2:37 pm - Tim Says:

    @Jim - I am using firefox on ubuntu. also have the same problem with epiphany. I tried applying Kevin’s patch to see if it would make any difference, and it does not. The image simply toggles to uploading, and the progress bar never moves. I do not get an image on the server side, and the file is not uploaded. Outside of that its damn sexy :) I wish I could get it to work for me…


  16. May 16th, 2008 at 2:42 pm - Jim Neath Says:

    @Tim - Will look into it today to see if I can get it working. I’ve have to move it over to Ubuntu I’ve got running on my PS3 (geek). I’ll see what I can do.


  17. May 16th, 2008 at 2:43 pm - Tim Says:

    Interestingly enough when I go to the fancyupload URL listed in this thread and try the demo I get similar behavior. So this is likely something that has to do with my flash installation and not your nifty project. sorry for the noise, I will see if I can debug whats going on in my local environment.


  18. May 16th, 2008 at 3:34 pm - Jim Neath Says:

    @Tim - Odd. Try setting the debug variable in /app/views/photos/index.html.erb to true and see what that spews out. Might be of some use.


  19. May 16th, 2008 at 8:20 pm - Tim Says:

    SWF DEBUG: SWFUpload Init Complete
    SWF DEBUG:
    SWF DEBUG: —– SWF DEBUG OUTPUT —-
    SWF DEBUG: Build Number: SWFUPLOAD 2.1.0 FP9 2008-05-12
    SWF DEBUG: movieName: SWFUpload_0
    SWF DEBUG: Upload URL: /photos
    SWF DEBUG: File Types String: *.jpg;
    SWF DEBUG: Parsed File Types: jpg,
    SWF DEBUG: File Types Description: Jpg Image Files (*.jpg;)
    SWF DEBUG: File Size Limit: 3221225472 bytes
    SWF DEBUG: File Upload Limit: 0
    SWF DEBUG: File Queue Limit: 0
    SWF DEBUG: Post Params:
    SWF DEBUG: —– END SWF DEBUG OUTPUT —-
    SWF DEBUG:
    SWF DEBUG: Event: fileDialogStart : Browsing files. Multi Select. Allowed file types: *.jpg;
    SWF DEBUG: Select Handler: Received the files selected from the dialog. Processing the file list…
    SWF DEBUG: Event: fileQueued : File ID: SWFUpload_0_0
    SWF DEBUG: Event: fileDialogComplete : Finished processing selected files. Files selected: 1. Files Queued: 1

    ————-

    There are apparently lots of people who are having issues with flash and ubuntu feisty, so I would chalk it up to that. There is one more line that gets added but the browser crashes before i can capture it. it always happens immediately after i click upload. I am going to give up on this and attribute it to a flakey ubuntu flash implementation (which is apparently well documented). Thankfully I have other computers I can use :)

    Tim


  20. May 16th, 2008 at 9:43 pm - masch Says:

    @Jim
    The only thing i got it’s:
    127.0.0.1 - - [16/May/2008:17:40:23 ART] “POST /photos HTTP/1.1″ 422 10629
    - -> /photos

    Salu2…


  21. May 17th, 2008 at 1:30 am - links for 2008-05-17 « Bloggitation Says:

    [...] SWFUpload, Paperclip and Ruby on Rails (tags: ruby rails programming) [...]


  22. May 17th, 2008 at 5:30 pm - links for 2008-05-17, or so says Harry Love Says:

    [...] SWFUpload, Paperclip and Ruby on Rails | Javascript (tags: rubyonrails flash uploading attachments paperclip) Tags: Found Objects [...]


  23. May 18th, 2008 at 12:30 am - links for 2008-05-17 « toonz Says:

    [...] SWFUpload, Paperclip and Ruby on Rails | Javascript (tags: upload flash) [...]


  24. May 18th, 2008 at 6:48 pm - swfupload in RoR « 轉折,然後向上 Says:

    [...] 五月 19, 2008 source: http://jimneath.org/2008/05/15/swfupload-paperclip-and-ruby-on-rails/ [...]


  25. May 19th, 2008 at 2:05 pm - Jim Neath Says:

    @masch - Can you let me know what browser/OS you’re using?

    @Tim - I’ve edited the article the point out that it’s basically fucked under linux. Thanks for bringing it to my attention.


  26. May 19th, 2008 at 6:28 pm - masch Says:

    I’am using Fedora 9 with Firefox 3 beta 5.
    Salu2..


  27. May 20th, 2008 at 5:43 am - tim Says:

    “Not tested on IE 6 because, quite frankly, it can fuck right off.”

    haha, I totally share that sentiment!


  28. May 20th, 2008 at 9:10 am - Jim Neath Says:

    @masch - As Tim has pointed out in the comments, there appears to be problems with using flash to upload files with linux.

    @Tim - I’m sick of testing things in IE6. I hate it, as I’m sure most developers/designers do.


  29. May 20th, 2008 at 3:33 pm - links for 2008-05-20 « Brent Sordyl’s Blog Says:

    [...] SWFUpload SWFUpload is a brilliant tool built with flash and javascript that allows you to upload multiple files at the same time, allows you to display progress bars and various other useful things. (tags: rubyonrails upload swfupload) [...]


  30. May 20th, 2008 at 11:20 pm - This Week in Ruby (May 20, 2008) | Zen and the Art of Programming Says:

    [...] Other remarkable articles from this week were: Chunky Iterator: So You Don’t Have to Load All Your AR Objects at Once, Do we really need Controller and View tests?, Guide to Unobtrusive JavaScript and SWFUpload, Paperclip and Ruby on Rails. [...]


  31. June 2nd, 2008 at 4:19 pm - taylor luk Says:

    Rails 2.1 Happy. !

    Add following for your controler

    class PhotosController false, :only => :create
    protect_from_forgery :except => :create


  32. June 8th, 2008 at 6:55 pm - deramoo Says:

    Thank you for this great work. But I met a problem with SWFUpload and Rails2 that my session data doesn’t seem to be correct. Here is the detail of the problem.

    I am using a two-page upload wizard. In the first page(Page A) you can select a catalog to upload the file, and on the second page(Page B) you select and upload the file itself. I put the catalog id into session after Page A, and get it back in Page B to create an active record. But when I get the ID back from the session, the ID seem like this:

    first time in Page A, I put 1
    first time in Page B, I get nil
    second time in Page A, I put 2
    second time in Page B, I get 1
    third time in Page A, I put 3
    third time in Page B, I get 2
    … …

    why this happens? any clues on solving this? Thank you.


  33. June 9th, 2008 at 5:55 pm - RubyPimp Says:

    I am trying to take this a step further and get this working with attribute_fu, As an example

    :person has_many :photos, :attributes => true

    Using this awesome plugin allows me to add multiple photos on the fly in form_for :person.

    Where I hit the snafu is the controller code. Since att-fu automatically builds through the association, you actually don’t need a controller for Photos at all. As a result I have no idea how to set the params for swfupload_file.

    Any ideas on how I can work around this?


  34. June 13th, 2008 at 10:35 pm - Michael Says:

    I am still getting the Massive Error issue. I don’t care for any type of security. How can I simply disable everything so as to just get this working?


  35. June 13th, 2008 at 11:13 pm - Michael Says:

    Ok, I now have it working. There was in issue in my “Create” method. One problem though, I can’t seem to control the sizes of the image previews during upload (some are ginormous) and all of the previews present as though they’re “partials” (although I removed that code). Any ideas?

    Thanks,
    Michael


  36. June 19th, 2008 at 4:01 am - Ken Says:

    By default, with rails 2.1.0, I get this:

    Processing PhotosController#create (for 127.0.0.1 at 2008-06-18 20:31:15) [POST]
    Session ID: be0fd9a1adcc1e75dc97ec4e930a1850
    Parameters: {”Filename”=>”signature.jpg”, “action”=>”create”, “Upload”=>”Submit Query”, “controller”=>”photos”, “Filedata”=>#}

    ActionController::InvalidAuthenticityToken (ActionController::InvalidAuthenticityToken):
    /opt/local/lib/ruby/gems/1.8/gems/actionpack-2.1.0/lib/action_controller/request_forgery_protection.rb:86:in `verify_authenticity_token’
    /opt/local/lib/ruby/gems/1.8/gems/activesupport-2.1.0/lib/active_support/callbacks.rb:173:in `send’
    /opt/local/lib/ruby/gems/1.8/gems/activesupport-2.1.0/lib/active_support/callbacks.rb:173:in `evaluate_method’
    /opt/local/lib/ruby/gems/1.8/gems/activesupport-2.1.0/lib/active_support/callbacks.rb:161:in `call’
    /opt/local/lib/ruby/gems/1.8/gems/actionpack-2.1.0/lib/action_controller/filters.rb:430:in `call’

    I had to comment out the ‘protected_from_forgery’ command in applications.rb to get this to work.

    I don’t understand how session handling works to determine how to make this work with sessions. Ideally, I would like to put image uploads behind a login screen, but unless I can get at the original session, there’s no way to do this.

    Hopefully somebody has some suggestions….


  37. June 19th, 2008 at 4:03 pm - Marcel Says:

    Ken, you should take a look at a Rails-generated form: you’ll see a hidden input-element right after the form-element is opened which contains an authenticity token. What it comes down to is that Rails expects this token to be posted along with every form-post you do to the application. It checks if the token from the form matches the token in application.rb to be sure the form is submitted by your app.

    A solution could be to somehow force the Flash-upload-thingy to include the authenticity token, but I’m not sure how to do this as I haven’t tried all this stuff out yet.

    Anyway, I hope you’ve got a clearer view on what’s going awry here.


  38. June 22nd, 2008 at 9:33 pm - Joel Says:

    Wow, man. This works like a charm! Thanks for getting all of this great info out here for the rest of us. I used the cues given from your sample app to get everything up and running in my app with the quickness. Kudos!


  39. July 2nd, 2008 at 3:02 pm - SWFUpload,Paperclip和Ruby on Rails配合使用的教程 - 全文检索博客 Says:

    [...] SWFUpload, Paperclip and Ruby on Rails 本文链接地址:http://blog.minidx.com/2008/07/02/1027.html [...]


  40. July 4th, 2008 at 6:26 am - charles Says:

    Jim —
    thanks for the brilliant post. It works like a charm.
    I had trouble using this with a sortable list as the id of the uploaded files’ div was based of off the flash file id and not the db row id.
    (it would work fine after a page refresh, but who wants that?)
    I came up with this modification to the upload.js file for anyone out there who might be interested:

    upload_success: function(file, data)
    {
    $(’#’ + file.id).replaceWith($(data));
    }

    This way the html element has the id you pass back from the controller in the partial data instead of SWF_0_x as the element id


Leave a Reply

Jim Neath is a 23 year old Ruby on Rails developer from Manchester, UK. Contact Jim Neath

Recommend Me

Categories

Stalk Me