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.

Update: Mika Tuupola has a good article on handling the server side (PHP) part of file uploading.

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.

Skip to comment form.

  1. @Bob – I’ve mentioned a few times in the comments of this article that goes into the serverside handling of the file upload. I’ve also updated the article to link to it.

  2. luokai says:

    please give me a Demo code ,this code isn’t upload.php file

  3. droid says:

    Brilliant! thanks for the demo.
    File opens in IE and Chrome but works a treat in FF
    Thanks for all the links posts too will give it all a good read… then drop files directly to database through PHP.
    Perfect for my project with special needs kids THANKS

  4. Dipak Basantani says:

    Hi Ninja,

    its really very cool functionalityand very good. I have implemented
    in one of my project.

    Still I got one problem.

    is there any limitation on the size of bytes on total files uploaded. If i upload total 7 files . each files are of more then 1 Mb size and seems like it does not upload the 7th file.

    and getBinaryDataReader.readAsBinaryString(file); gives error on upload. its exception error. so flow does not interrupted but the file was not uploaded.

    please suggest on this if you got any idea.

    Thanks

  5. Sarvesh says:

    Hello There,
    Thanks for such a nice plug-in, this is what I am looking for, This plugin is working fine on firefox,but it does not working on other browsers, Could u please focus on the same, so that user can enjoy the plugin for other browser.


    Thanks & regrads
    Sarvesh

  6. Ryan: It works fine. However, the upload.php script does NOT see any $_POST variables. The script gets called, but the $_POST array is empty. Using production 3.6 browser.

    Thoughts?

    Larry

  7. @Larry B

    Should you not be accessing the $_FILES super global to access uploaded files?

  8. manikavasakam says:

    how I can get the data in a JSP instead of php,any comments

  9. @manikavasakam

    Don’t know JSP so can’t help you there.

  10. Enrico says:

    Thank you very much for your the effort into this code, but please let me say that it is quite useless without a working upload.php file. I read the links you provided about and tried long to work it out, but without success. Many of us are not so proficiency in PHP to change the code to fit it into your example. So, meanwhile some guru publishes here a working upload.php, none of us will fully enjoy your code in our applications.

  11. Ryan Seddon says:

    @Enrico

    If you read the comments you’ll see I mention *many* times where to find server side help.

  12. pilus says:

    tested the live demo on chrome 12.0.742.112/Win, there’s an error popped out on the devtool’s console, it says:

    Object # has no method ‘addEventListener’
    on: /demo/drag-drop_upload/v2/:114

    I think the latest File API don’t have addEventListener or something, but i’ve successfully implemented the same functionality using:

    FileReader.onloadend = function(){};

    and it works on chrome 12, FF4/5, and opera 11

    the only problem that I have is with readAsBinaryString on file larger than 100KB, the onloadend seems to never called, even after waiting for 10 minutes (yupz, i actually waited for that long …. @__@)

    as you might already know, i use readAsBinaryString for uploading to the server … but i never got a chance to upload anything, as everytime i try to readAsBinaryString it never ends … >.<

    would really appreciate some help, tried googling this, but doesn't seem to be anything to help me …

    in the meantime will try to slice the file for readAsBinaryString, it that's possible at all …

    cheers

  13. Praveen says:

    I went through all the above post but your are redirecting to http://www.appelsiini.net/2009/10/html5-drag-and-drop-multiple-file-upload when ever some one asks for the server side script.

    I tried many ways with $_POST, $_FILES and then finally file_get_contents(“php://input”). $_POST and file_get_contents(“php://input”) are returning some data which is not giveing proper result when sent to image tag in PHP as below
    $file_data = file_get_contents(“php://input”);
    print “”;

    This is not useful for me until I store the posted data into server.

    If anyone have got success with PHP. Please paste the code in this thread.

    Thanks

  14. Ryan Seddon says:

    @pilus

    Yes I too came across DOM2 event handling not working on FileReader, I filed a bug a long time ago but it still hasn’t been fixed.

    Haven’t come across your issue with readAsBinaryString not working. Do you have a testcase for this?

  15. Hi Ryan,

    Thanks so much for providing this demo. The code reads really well and is a great starting point I feel for many developers (including me) getting their head around the Drag and Drop capabilities.

    Keep up the great work.

  16. Similar to your code i’ve came up with this
    http://www.ashantyk-design.com/dev-3-Upload%27em+JS

    I said similar because i pulled out the % loading thing because that shows the progress of the file being loaded into the browser, not the server and i put in a connection limit part with queueing.

    Also i extended the delete/cancel function. users can delete uploaded files after upload completion, using a session variable so they won’t delete any files that they didn’t uploaded (security reasons)

  17. Nenad says:

    Hi Ninja!

    Great work! I was inspired by your drag and drop uploader so I rewrote it and optimized it to work also in chrome browser.

    The demo is on:

    http://www.ninja-scripts.com/demos/drag/

    and the uploaded files:

    http://www.ninja-scripts.com/demos/drag/files

    Regards,
    Nenad

  18. zero says:

    Can the demo work?

    Uncaught TypeError: Object # has no method ‘addEventListener’

  19. Ryan Seddon says:

    @zero –

    There’s been a long standing bug in Chrome not supporting DOM2 event binding on FileReader().

    However you can use DOM0 event binding to get around in the mean time.

Leave a comment