I’ve just completed the upgrade of the DojoX FileUploader to make it compatible with Flash Player 10. The FileUploader widget allows for the uploading of more than one file at a time, which is surprisingly still not supported natively by any web browser on the market today.

In Flash versions 8 and 9, a file upload Browse Dialog could be launched using JavaScript code. Users could click an HTML button, which would call a JavaScript function behind the scenes, communicate with a Flash (SWF) file, which would then trigger the browse() method in the SWF. The latest Flash Player has a security feature where the user must click within a Flash-based portion of the user interface to launch the Browse Dialog. This change is to prevent malicious code from continually opening the dialog without user interaction. Working toward this upgrade was a major undertaking that involved a significant rewrite of FileUploader. The results are a success, and in addition to working with the tightened security policies, it was a great opportunity to add many new features:

  • Degradable
  • CDN Support (see below for cross-domain restriction details)
  • POST Data Support
  • Custom Field Name Support
  • Full Event Support
  • Exposed CSS Positioning
  • Dialog Container Detection

Degradable

As it worked before, the FileUploader detects if the browser has the Flash plugin version 9.0 or greater installed, and if so, initializes the Flash FileUploader. If not, a conventional fileInput is used. You can always set the force parameter to either “flash” or “html” to require a particular version of the FileUploader and override the detection. By default, force is an empty string, triggering the detection.

CDN Support

Dojo’s CDN is very important system for the Open Web, but occasionally there are issues since the JavaScript is being served from a different domain than the page launching the code. This is compounded by security restrictions within Flash. The FileUploader embed code now contains the proper parameters to enable communication and execution between the FileUploader SWF and JavaScript belonging to different domains:

allownetworking="all"
allowscriptaccess ="always"

However, there are still limitations to what can be done over the CDN. The SWF must be from the same domain as the HTML page – it will currently not work with the SWF on the CDN server. We’re still investigating possible solutions for serving the FileUploader SWF from the CDN. In the meantime, the swfPath parameter has been exposed so that you may link to a local SWF, which of course could be the same SWF downloaded from the dojox/form/resource folder.

POST Data Support

You can now pass in POST data that will be posted to the server along with the Flash uploaded files. Previously, this could be done by appending variables to the URL, but that was unreliable. I’ve tapped into the Flash feature that appends the data for you:

//ActionScript
request = new URLRequest(uploadUrl);
request.method = URLRequestMethod.POST;
request.data = getPostData();

Additionally, if the HTML FileUploader is used, the postData object will be converted into hidden fields and posted to the server.

Custom Field Name Support

You can now specify the field name that the server expects to find the files. Flash defaults to using the Filedata field name for the files, which is fine if you are customizing the server or building it from scratch. But naturally, some systems are already in place and such a change may not be desirable. Simply set the flashFieldName parameter, and that’s what will be sent. The htmlFieldName is used for the HTML version of the FileUploader.

Full Event Support

I went to great lengths to expose as many events as possible. All the mouse actions have event methods that can be connected to since they are already used for emulating the hover state of the ‘fake’ button — the styled button that acts as the stand-in for the actual upload button. The canceling of the dialog window is captured in Flash and passed to a method in the FileUploader. In order to mirror that functionality with the HTML FileUploader, I noticed the onMouseOut() event of the fileInput does not fire until the dialog is closed. By checking that a file was not selected, I can create a pseudo cancel event and pass that to the onCancel() method.

Exposed CSS Positioning

Now that the Flash FileUploader has to use the same CSS hacks as the HTML FileUploader, it was more important than ever to get the positioning right. It’s been tweaked and massaged, and I have it working for several different use cases. However, because of the nature of this “hack”—floating a zero-opacity fileInput or a transparent SWF over a “fake” button—this won’t work in all circumstances. For instance, the uploaders won’t work properly in a scrolling div. CSS rules can unexpectedly cause placement issues. Placing the FileUploader near the bottom of a complex document can throw off the positioning. The positioning methods have been exposed for overriding in these cases. The setPosition() method can be called whenever there has been a screen redraw that may upset the placement. For certain cases not covered, it’s just a matter of replacing the setFlashPosition() and/or the setHtmlPostion() and using your own code.

Dialog Container Detection

In my experience, a very common use case for the FileUploader is within a Dijit Dialog. I’ve written a script that walks up the DOM tree and checks if the ‘fake’ button is a child of a Dialog. If so, the show() and hide() methods of the Dialog are connected to—since we don’t want an invisible Upload button floating around our document. The dragging of the Dialog box also triggers the setPosition() to keep it in place.

Summary

File uploads are common on the web, but browsers still provide a poor user experience for multiple-file uploads. The SitePen and Dojo teams are striving to make it as easy as possible to implement a great experience for your users. The new DojoX FileUploader will be available in the forthcoming Dojo 1.3 release, any Dojo nightly build, or from Dojo’s Subversion repository. Please send us your feedback and feature requests, or if you need assistance implementing this within your application, check out our services.