The File API has changed
Recently I have been touting how awesome and revolutionary the File API is through a few demo’s. After some feedback on webapps mailing list there have been some major changes to the API and how it works.
I have updated my previous drag and drop upload demo to reflect the API changes, as of Firefox 3.6b3 the API supports both the original API and the updated one. The older model will eventually be dropped, it’s only in there for legacy purposes. To use the demo you will need Firefox 3.6 installed. You can also watch the screencast of it in action.
The biggest change is with the file handling, it is now processed asynchronously with progress events so we can attach listeners. The advantage of this is if a user drags in many files or a large file the UI won’t be locked up while it’s processing the data, much like XmlHttpRequest works.
The File object
The File object has been updated to reflect the new specs changes and has deprecated all the previous methods we used to get the file in various formats e.g. getAsDataUrl(), getAsText(), getAsBinary(). We now handle these methods in the new FileReader object.
It has also renamed the 2 properties for accessing the files name and size from fileName/fileSize to name/size respectively.
The FileReader object
This new object allows us to asynchronously read the contents of a file from a drop event.
var reader = new FileReader(); reader.addEventListener("loadend", TCNDDU.buildImageListItem, false); reader.readAsDataURL(file);
Instead of locking the UI while we wait for it to loop through all the dropped files and then convert them to a DataUrl. The FileReader does this asynchronously. We attach to the onloadend event handler which will fire once the current file has been read into the result attribute. Upon the event firing we then take the event result and add the DataURL to the source of the image to be displayed to the user while it uploads.
Send the binary data
Once we have the file we send it to be processed for an XHR call so we can upload it to the server. Same as above we need to create a file reader and attach to the onloadend event which we then pass to the sendAsBinary() method.
var getBinaryDataReader = new FileReader(); getBinaryDataReader.addEventListener("loadend", function(evt){xhr.sendAsBinary(evt.target.result);}, false); getBinaryDataReader.readAsBinaryString(file);
Similar code we used for the image display handling, but we use the readAsBinaryString() method to return the files binary data for uploading.
Further reading
As the 3.6 final release date is coming closer Mozilla has been ramping up demos and documentation about the File API. Some good documentation on handling files in web applications.
The hacks blog has recently put up some great information about the File API along with an excellent demo extracting EXIF data from an image.
Now we just need webkit to push out the File API to their nightly builds.
Post filed under: html5, javascript.
Comments
Trackbacks
-
[...] This post was Twitted by kilianbarrera [...]
Any word on how this will play with Safari? I’m working on a site that only need to support FF and Safari and this could be a great addition.
Luke, January 23rd, 2010Not sure when they will implement the File API, but there has been a bug filed on webkits bug tracking site requesting they add it.
The Css Ninja, January 23rd, 2010Nice work!
surreydude, February 5th, 2010Tested the demo to work in the release version of Firefox 3.6. Very cool. I noticed after the image is “uploaded” it outputs the image as a base64 encoded data URI… any reason you’re doing this instead of storing the image on the server?
I assume it is possible to simply store the image on the server if desired.
Michael Butler, February 6th, 2010@Michael – It’s actually encoded into a base64 string before it uploads (using the File API). That way I can display the image to the user before any uploading happens. If you disable your network connection and drag in the images it will still display them but will obviously fail on trying to upload them to the server.
The Css Ninja, February 6th, 2010That makes sense! I can see how easy it is then to use the offline data API to store the images locally and upload them later on. Can’t wait to try this out.
Michael, February 6th, 2010When I try the demo in FF3.6 on Ubuntu, Firefox tries to open the dropepd document, instead of uploading them. It seems to ignore the File and Drag And Drop APIs.
Émile Jetzer, February 28th, 2010@Émile – That’s not good, I don’t have a linux machine available for me to test on so I can’t see what’s happening. Can you try my font dragr web app (it uses the file API too) in FF3.6 on your linux machine and let me know if you have the same issue?
The Css Ninja, March 1st, 2010The font dragr doesn’t work either. It seems to be exactly the same issue.
Émile Jetzer, March 1st, 2010@Émile – So I asked around for a few people with linux to try my demo and it’s working for them, but someone did mention that having the Jetpack add-on installed kills the drag and drop functionality but only on linux machines, mac/windows are OK. It’s been filed in the issue tracker so they’re aware of it.
The Css Ninja, March 2nd, 2010I disabled Jetpack, and now it works all right! Thank you!
Émile Jetzer, March 6th, 2010This is really cool! Ubuntu/Firefox isn’t working for me (no Jetpack here), but it works great on my windows machine. I’m going to hack on it for a while to see if I can figure out where Linux is going wrong…
Shawn, April 7th, 2010Shawn, don’t have a linux box to test on so I can’t help you on that front. Only linux issue is the Jetpack plugin but you’ve stated you don’t have it. If you figure out the problem I would be interested to know what it was.
The Css Ninja, April 7th, 2010Could you update your article to include a little blurb on how update.php handles it? As in: $_POST['what goes here???']. I don’t see a name property set anywhere for the post data in your code…
Curt, April 24th, 2010Curt, have a look at this article as it goes into handling the server side of the upload, should help you out.
The Css Ninja, April 24th, 2010@Curt
Alexander Romanenko, May 15th, 2010Using some inspiration from this article, I came up with a JSON solution to upload both binary and/or user data.
http://alex-tech-adventures.com/development/x-html–css–javascript/97-drag-and-drop-upload-using-html5-with-firefox.html
hi,
i’m trying to get the server site working :
my upload.php server side is a simple var_dump($_FILES)
i added an event listener for the ready state change for the xhr to log the response
i get an empty array
firefox 3.6
Guillaume, May 19th, 2010php 5.2.10
apache 2.2.11
on windows XP 32b
Looks nice, but how to store the files on the server?
I’m sorry if I read over this – English is not my first language..
The article you postet on April 24th doesn’t want to help me
Holger, May 23rd, 2010any chance you could let me know how to add “cancel (single object)” and/or “cancel all” method(s)?
chris malcolm, June 6th, 2010Thanks for the sample, really helped me a lot!
However, I discovered a small bug in the handleDrop() function which prevents the file name from being propagated past the drop event. Not really a big deal, but for what I’m doing some information is encoded in the file name which I need to access between the drop and the upload. Anyways, to fix the issue line 96 should be setting reader.name to droppedFileName.
Clark, June 18th, 2010know how I can get the data in a JSP instead of php,because I need to upload the files using JAVA
salvador, June 19th, 2010I just finished a jQuery plugin for this:
http://github.com/weixiyen/jquery-filedrop
Assuming Webkit follows suit, this should be future-compatible, but it works perfectly with FF3.6 right now.
Weixi Yen, June 22nd, 2010WoooWW
Farzan mc, June 23rd, 2010Best thing ever in html
I saw this in gmail and later on in google wave presentation, i didn’t think that i can find the source code …..
Thanks a lot, it will sure come in handy in my projects.
Wooooooooooow
@Chris M – Not sure what you mean. You want to be able to cancel an image upload?
The Css Ninja, July 5th, 2010@Salvador – Not familiar with JSP but I’m sure they share similar functions. Might be better off asking on a JSP forum.
The Css Ninja, July 5th, 2010@Holger – Have a look at the previous comment I made it has a link to a website which goes into handling the data on the server side.
The Css Ninja, July 5th, 2010I was implementing some of these features by looking in your zip file download… ran in to an issue where you do:
fileUpload.log = container;
But the log property doesn’t carry over 90% of the time in the load event of the XHR… you must have realized this because this part is commented out in your live demo, which uses anonymous functions to keep a handle on the progress bar!
Michael Butler, August 15th, 2010@Michael B – Ah must of forgot to update the demo files zip file, thanks for pointing that out. Source files zip is updated now.
The Css Ninja, August 15th, 2010One of the problems I keep coming up against with drag & drop is the lack of affordance. Even in gmail– I don’t know that I can drag and drop an image until I’ve already tried it, and the actual area I can drop my files in isn’t the “Rich Text” portion of the app, which is debatably where I’d want to see my file.
One of the things I’ve tried is to simply swap classes on input, so that if the user drags a file into the window, the entire window can receive the file. Otherwise, style it to look like a button in my rich text editor so that it behaves normally.
After successful drop, a small “Uploading” message is set with a fixed position, similar to gmail’s “sending…” message.
Upon successful upload, the final file location(s) (I’m resizing along the way) are sent back as jsonp so that img tags can be generated and inserted into the rich text editor.
Not feasible for say, a CMS with multiple Rich Text fields, but less does indeed seem to be more when it comes to managing user expectation of how dropping files should operate.
Adam, September 2nd, 2010I should note it really doesn’t solve the affordance problem, it just seems to be what laypeople expect from my limited experience testing :]
Adam, September 2nd, 2010@Adam – There’s nothing stopping you attaching a drop event on the body which will capture the drop no matter where the user drops it.
The Css Ninja, September 2nd, 2010