Jim Neath

Manchester based Ruby on Rails & Facebook App Developer

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 also 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.

You can 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

blog comments powered by Disqus

I am available for freelance work! Click here to email me.

Jim Neath is a Freelance Ruby on Rails & Facebook app developer from Manchester, UK, currently working for Engine Yard.