by Christian Cantrell

Christian Cantrell


17 November 2009

Prerequisite knowledge

This article is intended for developers who
are comfortable with ActionScript 3. Some
experience with Adobe AIR is
Required products

User level

One of the biggest advantages of building an Adobe AIR application rather than (or in addition to) a browser-based application is the availability of desktop APIs. For example, AIR applications can access the file system, create native windows for desktop notifications, and have full access to the system clipboard for copy-and-paste as well as drag-and-drop operations. But as more and more data is being moved online, it's increasingly common for files to be stored remotely rather than on your local machine. AIR has always provided excellent networking APIs for accessing remote data, but until the introduction of file promises in AIR 2, it has never been possible to drag remote files out of an AIR application.
A file promise is what you put on the clipboard when you want the user to be able to drag and drop files that do not yet exist, or that exist elsewhere (not locally on your machine). For example, files that are on a remote server, or files that you only want to generate (such as a CSV file) when the user tries to drag and drop them. A file promise isn't an actual file; rather, as its name suggests, it represents the promise to deliver a file at some point in the future, after the user has selected a drop location.
This article covers the following topics:

About the clipboard

Adobe AIR gives developers full access to both reading and writing from the system clipboard. In general, the clipboard is used for placing data for other applications to access; you can also create your own clipboard instances to allow dragging and dropping across applications. The following snippet shows a simple example of putting a string on the general clipboard so that it can be pasted into another application:
import flash.desktop.ClipboardFormats; var toCopy:String = "Hello, Adobe AIR."; Clipboard.generalClipboard.clear(); Clipboard.generalClipboard.setData(ClipboardFormats.TEXT_FORMAT, toCopy);
Here's a simple example of placing some text on a clipboard for dragging out of your AIR application:
var toDrag:String = "Hello, Adobe AIR."; var cb:Clipboard = new Clipboard(); cb.setData(ClipboardFormats.TEXT_FORMAT, toDrag); NativeDragManager.doDrag(someComponent, cb);
The following list shows all the data formats that the Adobe AIR clipboard supports (as defined in the ClipboardFormats class):
Note: Data placed on the clipboard is available to any other application that wants to access it, not just other Adobe AIR applications.
To put files on the clipboard that you currently have a reference to, you use the FILE_LIST_FORMAT clipboard format and pass in an array of File objects. To put files on the clipboard that you do not yet have—a reference to (for example, files that exist on a remote server)—you use the FILE_PROMISE_LIST_FORMAT clipboard format and pass in an array of objects that implement IFilePromise.

Writing your own file promise implementation

Since a file promise is a promise to get a file at some point in the future, the AIR runtime needs to know how to get that file. It might be that the file exists on a remote server, or that it simply hasn't been created yet. The IFilePromise interface is the contract between the runtime and the developer which describes how a file that doesn't exist yet will exist when the operating system asks for it.
An IFilePromise implementation must provide the following three methods:
  • open: Must return a reference to an object that implements IDataInput.
  • close: Called when the runtime is done reading from the IDataInput.
  • reportError: Called in the event that the runtime experiences an error while reading from the IDataInput object.
An IFilePromise must also define two properties:
  • isAsync: Specifies whether or not the data provided by the IDataInput will be provided synchronously or asynchronously. If it will be provided asynchronously (which will probably be the case most of the time), your IDataInput must also implement IEventDispatcher so that progress events can be thrown. If isAsync returns false, it is expected that the data will be available immediately.
  • relativePath: The path of the file that will be created relative to the drop location. For example, if relativePath is NewMusic/foo.mp3 and the drop operation occurs on the desktop, the final destination of the file on Mac OS X or Linux will be ~/Desktop/NewMusic/foo.mp3.
Having the option of implementing your own IFilePromise means that you have a great deal of flexibility in how your file gets created. You might generate it on demand, retrieve it from an FTP server, or you might download it over HTTP. But we figured that in most cases, developers will want to download file promises from a remote server, so we went ahead and created an implementation of IFilePromise called URLFilePromise so that you wouldn't have to.

Using URLFilePromise

The URLFilePromise implementation of IFilePromise makes putting files that are located on a remote HTTP server extremely simple. For example, if you had a DataGrid called fileData full of information about files on a remote server, the following code is all you would need to enable your end user to drag and drop those files out of your application:
var cb:Clipboard = new Clipboard(); var items:Array = fileData.selectedItems; var promises:Array = new Array(); for each (var item:Object in items) { var fp:URLFilePromise = new URLFilePromise(); var req:URLRequest = new URLRequest(item.url); fp.request = req; fp.relativePath =; promises.push(fp); } cb.setData(ClipboardFormats.FILE_PROMISE_LIST_FORMAT, promises); NativeDragManager.doDrag(fileData, cb);
When your end user drags one or more files out of your data grid and drops them anywhere on the file system, all the selected files will be downloaded in the background as quickly as possible (through multiple network connections, if possible) and will appear as they arrive.
If you want to asynchronously monitor the progress of the file downloads, be sure to register for the PROGRESS event. Additionally, you may want to register for the COMPLETE and HTTPStatusEvents so that your application can stay informed of the state of the downloads.
Some things to remember
Below are a few things to keep in mind when using file promises:
  • File promises only work with drag-and-drop operations (not with copy and paste). You cannot put file promises on the general clipboard for end users to paste. (Actually, you can, but setData will return false indicating that it won't work.)
  • File promises only work between an AIR application and the native file system. You can't use file promises to drag and drop or copy and paste between AIR or native applications.
  • If a file promise fails for any reason, the partial file is automatically removed from the file system so your code does not have to worry about cleaning it up. Previously downloaded files will not be deleted, and subsequent downloads will still be attempted.

S3E: File promises in action

S3E is an AIR application that I wrote for managing files stored on the Amazon S3 service.
In my original version, to get files into the application (and transferred over to S3), you could use copy-and-paste or drag-and-drop support. To get files out, however, you could only choose to copy them, which downloaded them in the background and then placed them on the clipboard. There was no way to drag a representation of a remote file out of the application and drop it on the local file system to be downloaded to the chosen location.Thanks to file promises, the newest version of S3E now supports dragging and dropping of multiple files in both directions. You can install S3E from the AIR Developer Center, or download the source code from Google Code.

Where to go from here

This article covers the basics of drag-and-drop, described writing your own IFilePromise, and demonstrated the use of the URLFilePromise. For more information on file promises, see: