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.
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:
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
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
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.
You can grab the example application from github: