Merb was originally created by Ezra Zygmuntowicz to avoid some Rails upload issues.
This is one of the things that Merb was written for. Rails doesn‘t allow multiple concurrent file uploads at once without blocking an entire rails backend for each file upload. Merb allows multiple file uploads at once.
I’ve built ‘multiple’ file uploaders for Rails sites but they always involved some slight of hand, the files appeared to be uploading all at once but they where actually queued up by Flex then handled one by one by the app (which also had the unhappy side effect of blocking any other requests to that process). I’ve been wanting to try out Adobe AIR’s file system drag and drop for a while so this is a two-fer example. You’ll need the beta version of Flex Builder 3 or the Flex 3 SDK beta if you don’t mind getting down with the command line.
In a hurry? Here’s one I made earlier (flex source in ‘).
If you haven’t before install Merb
Then create a new Merb app
and dive on in
We’ll need two folders not in a Merb skeleton, one for Flex, and one for our uploads
Create a local database called ‘merb_air_upload’ and edit dist/conf/merb_init.rb so that the database definition matches your setup
# set your db info here
ActiveRecord::Base.establish_connection(
:adapter => 'mysql',
:username => 'root',
:password => '',
:database => 'merb_air_upload'
)
Our model will be called ‘UserFile’ as ‘Upload’ and ‘File’ are reserved words, create a migration
and edit it (dist/schema/migrations/002_create_user_files.rb) to look like so
create_table :user_files do |t|
t.column :filename, :string, :null => false
end
end
drop_table :user_files
end
end
rake your db
Then create a UserFile model (dist/app/models/user_file.rb)
end
and an upload controller (dist/controllers/upload.rb)
# for testing check jer terminal
puts params.inspect
# new user file object
@upload = UserFile.new
@upload.filename = params[:Filename]
# save
if @upload.save
# create directories
dist_root = Merb::Server.config[:dist_root]
FileUtils.mkdir dist_root + "/public/uploads/"
# move
destination = dist_root + "/public/uploads//"
FileUtils.mv params[:Filedata][:tempfile].path, destination
else
false
end
#render_no_layout
end
end
That’s it for the Merb side of thing on to our AIR app, fire up Flex Builder and create a new AIR project

I like to keep my flex files in my Rails/Merb app directory

The AIR app is three files; the main MXML file (dist/app/fx/merb_air_upload.mxml), a code behind class (dist/app/fx/com/vixiom/merb_air_upload/App.as), and an upload progress component that gets repeated for each file (dist/app/fx/com/vixiom/merb_air_upload/UploadProgressComponent.mxml). Here’s the main MXML file:
It’s hooked up to it’s code behind ‘App.as’ class by the xmlns tag ) App.as extends WindowedApplication which is the base of all AIR apps:
package com.vixiom.merb_air_upload
{
import com.vixiom.merb_air_upload.UploadProgressComponent
import mx.core.WindowedApplication;
import mx.containers.VBox;
import mx.controls.Button;
import mx.events.FlexEvent;
import flash.events.*;
import flash.desktop.*;
import flash.filesystem.File;
import flash.net.*;
public
{
private var filesToUpload :Array
private var UploadProgressComponents :Array;
public var files_vb:VBox;
public var upload_btn:Button;
private var uploadURL:URLRequest;
/*
* Constructor
*/
public :void
{
addEventListener( FlexEvent.CREATION_COMPLETE, creationCompleteHandler );
}
/*
* creationComplete
*
* called when the AIR has finishe loading, sets up drag/drop event listeners reference objects
*
*/
private :void
{
addEventListener( NativeDragEvent.NATIVE_DRAG_ENTER, onDragEnter );
addEventListener( NativeDragEvent.NATIVE_DRAG_DROP, onDragDrop );
upload_btn.enabled = false;
upload_btn.addEventListener( MouseEvent.CLICK, upload );
uploadURL = new URLRequest();
uploadURL.url = "http://localhost:4000/upload";
uploadURL.method=URLRequestMethod.POST;
filesToUpload = new Array();
UploadProgressComponents = new Array();
}
/*
* onDragEnter
*
* files have been dragged into the app
*/
private :void
{
DragManager.acceptDragDrop(this);
}
/*
* onDragDrop
*
* when files are dropped...
*/
private :void
{
DragManager.dropAction = DragActions.COPY;
var files:Array = event.transferable.dataForFormat( TransferableFormats.FILE_LIST_FORMAT ) as Array;
for each (var f:File in files)
{
addFile( FileReference( f ) );
}
upload_btn.enabled = true;
}
/*
* addFile
*
* ...add then to filesToUpload array, and the file upload listeners,
* and create a progress component for each file
*/
private :void
{
filesToUpload.push( f );
var upv:UploadProgressComponent = new UploadProgressComponent();
UploadProgressComponents.push( upv );
files_vb.addChild( upv );
upv.file_lb.text = f.name;
upv.pb.source = f;
f.addEventListener( Event.COMPLETE, completeHandler );
f.addEventListener( IOErrorEvent.IO_ERROR, ioErrorHandler );
}
/*
* completeHandler
*
* a file upload is complete, remove it from filesToUpload
* and remove the upload component
*/
private :void
{
var f:FileReference = FileReference(e.target);
for( var i:uint; i < filesToUpload.length; i++ )
{
if( f.name == filesToUpload[i].name )
{
files_vb.removeChild( UploadProgressComponents[i] );
filesToUpload.splice(i, 1);
UploadProgressComponents.splice(i, 1);
}
}
}
/*
* trace any errors
*/
private :void
{
trace("ioErrorHandler: " + event);
}
/*
* upload!
*/
private :void
{
for each (var f:File in filesToUpload)
{
f.upload( uploadURL );
}
}
}
}
The last file is the upload progress component, it’s progress bar listens for events from each file (upv.pb.source = f; above in the addFile method)
That’s it! test your AIR app by dragging some files from the file system, once you drop them the upload progress components show a visual representation of the files, click ‘upload files’ and the files are upload all at once (for real real not for play play this time).

drag!

drop!

upload!
29 Comments
Awesome. I have been wanting to play with Flex and Merb and now you have given me some gound to work on. Cheers
Very cool. It’s awesome to see Merb getting more use.
Hey, u once fancy jerself w/PHP…….would love to see this on php, or on the same realm CAKEPHP?
any chance?
Tomo I know you’re smart enough to make a PHP version, the upload script is ‘cake’ so it could be done in Cake. How about a Strata version
Yeah, I know…. I just wanted to tempt ya back to the php side
. Strata, heh, haven’t touch dat in a while.
Great example, much appreciated and well done.
thanks Evan,
Let me know when flexheads.com is launched, I use Cairngorm on some larger projects but still haven’t wrapped my brain completely around it.
Update for flex3 beta 2, change the line in onDrop from:
var files:Array = event.transferable.dataForFormat( TransferableFormats.FILE_LIST_FORMAT ) as Array;
to:
var dropfiles:Array = event.clipboard.dataForFormat(flash.desktop.ClipboardFormats.FILE_LIST_FORMAT) as Array;
and add
import flash.desktop.ClipboardFormats;
And if I double checked before posting I could fix my code to match the code here.
var files:Array = event.transferable.dataForFormat( TransferableFormats.FILE_LIST_FORMAT ) as Array;
to:
var files:Array = event.clipboard.dataForFormat(flash.desktop.ClipboardFormats.FILE_LIST_FORMAT) as Array;
Hi! Looks like great work!
Is it possible to combine this with a rails app? I’d like to just use merb for uploading, so I’d like to be able to open the uploader from my rails app. Can anybody give me some hints on how to do that? Another thing I’m curious about is how the merb and the air application communicate with each other – I’m relatively new to web development. Also does anybody know about how to add a button to the AIR app for adding files for uploading, using a “traditional” file dialogue? And are there any problems with deploying a rails app that also has a MERB part?
Very nice.
Can this work with an HTTPS upload URL?
Thanks, Gerry
Gerry,
I haven’t tried it with HTTPS, I know with Flex the Flash player there are special security requirements when using HTTPS http://livedocs.adobe.com/flex/2/langref/flash/system/Security.html#allowDomain() not sure if that also applies to AIR.
doh that link got cut off the HTML anchor should include the parenthesis after ‘allowDomain’ http://livedocs.adobe.com/flex/2/langref/flash/system/Security.html#allowDomain()
Ruby is the programming language under which the Ruby on Rails framework runs. Merb is not a Ruby on Rails gem but a Ruby gem. Merb is a MVC web framework similar to Rails. Please do not confuse the two, Ruby is the language, Rails is the framework.
Thank you fricking captain of the programming police.
Hi,
I’m having a little trouble when importing the ‘In a hurry’ version into Flex as an Existing Project.
I instantly receive these errors having made no changes to the code:
1119: Access of possibly undefined property transferable through a reference with static type flash.events:NativeDragEvent.
1120: Access of undefined property DragActions.
1120: Access of undefined property DragManager.
1120: Access of undefined property DragManager.
1120: Access of undefined property TransferableFormats.
I feel as though I am missing something very simple here, any help would be greatly appreciated!
D.Kumar
Hey,
It looks like the Flex Drag classes have changed in Flex Beta 3 (this was made with Beta 2), Merb has also changed since this post, such is the life of living on the egde!
I’ve posted a fix here http://actionsnip.com/snippets/vixiom/merb-on-air-fix-for-flex-beta-3
BTW your the first to see actionsnip.com as I just released it yesterday
- Alastair
Hi Alastair,
Thank you for the swift response, my Flex project with the drag and drop feature now works very nicely
However… the problem I have now is that MERB is not allowing me to perform a db:migrate. I’ve checked the methods inside the MERB app and the db:migrate method does not exist. I have tried various things to run db:migrate but have not been successful.
Again, any help would be greatly appreciated. This is the last step that is needed to complete the project for me.
Oh, also, I’m impressed with your website, looks like a useful resource for me.
D.Kumar
Okay, last one I promise!
Here we go…I figured out why the rake db:migrate was not working. The reason was because I had forgotten about the configuring of a database with MERB as MERB does not come with database support. Anyway, MERB connects fine with the database but the rake db:migrate does not work because it cannot find the schema.rb file even though it exists in dist/schema/schema.rb.
Thoughts, suggestions, plain old pointing out the obvious would help me so much,
D.Kumar
Hey, does this solution work with Files bigger than 100MB?
Thanks,
Marcel
Hi Marcel,
I’m not sure if this applies to AIR apps but I know Flash file upload only handles files less than 100mb.
could u send code for upload videos files in flex and send its data to rails ?
hi
how can i intregate the air aplication with php to upload files to a ftp server
Hello,
Thank you very much for posting the code for this app. Would it be tough to modify this air-application to be a regular flex application? Thanks.
Nice tutorial. Can i get the source files please??
am i missing something really obvious, the merb -g appName, just gives errors, if i use merb-gen i dont get the same folders and some of the scripts are missing, can you point me in the right direction?
thanks
Is it possible to have the files upload one at a time instead of simultaneously? If so, how can I do that?
Can you post a new link to the Flex 3 version, the posted link is dead.
thanks
Hi the drag and drop code works fine….How to do this in the case of mp3 files instead of images.and also i want to drag an mp3 file from AIR to desktop.
11 Trackbacks
[...] I also ran through the Merb/AIR tutorial here: Merb on AIR – Drag and Drop Multiple File Upload. [...]
[...] Check out this AIR tutorial for Drag and Drop Multiple File Upload using Merb and AIR.You need Flex builder 3 Beta for this. more @ http://blog.vixiom.com/2007/06/29/merb-on-air-drag-and-drop-multiple-file-upload/ [...]
[...] and Drop Multiple File UploadHere is the tutorials about Drag and Drop Multiple File Upload.It’s actually using Flex 3 and Adobe AIR.The server side is using the Ruby on Rails gem Merb to [...]
[...] Merb on AIR – Drag and Drop Multiple File Upload – A slightly old (June 2007) tutorial demonstrating how to use Merb alongside an Adobe AIR powered client to handle file uploads. [...]
[...] http://blog.vixiom.com/2007/06/29/merb-on-air-drag-and-drop-multiple-file-upload/ [...]
[...] And raw byte access is enabling everything from image and video encoding, to email clients to ftp clients, just weeks after AIR is launched. And heck, I nearly forgot about the online / offline [...]
[...] Drag and Drop Flex File Upload with Ruby on Rails [...]
[...] and Drop Multiple File Upload Here is the tutorials about Drag and Drop Multiple File Upload.It’s actually using Flex 3 and Adobe AIR.The server side is using the Ruby on Rails gem Merb to [...]
[...] Whilst writing an Adobe Lightroom plugin to upload library items to a rails app, i spotted something i definitely need to play with! Adobe Air and Merb file uploader. Looks rather handy! [...]
[...] Next, I’ll be adding Ruby-Processing and setting up BlazeDS, and finally I’m going to be making a Merb back-end to accept multiple simultaneous file uploads to a CouchDB store via an Air client app similar to the the one the Vixiom guys described a year ago here. [...]
private air…
DojoCampus ” Blog Archive ” Dojo and Air, a fancy file uploader is an excellent site and I have to say that I am really impressed….