Fun with the File API

Working with Files has always been exclusively a "server thing". No more, enter the File API and his buddies. This API allows you to work with files directly in the browsers. You can read, modify, and create them right then and there, and let the user save the result.

So what could we do with this?

Warning, this example will not work in Safari or Opera!

Download the above text:

Download as .txt Download as .html

Let's make an animated gif!

How does it work?

The Files API looks a lot tougher than he is, sort of like a guy with a goatee who smokes cigars but actually enjoys peppermint tea and horticulture. Anyway, we digress. We basically have to create a new Blob(["data", "more data"], {"type" : "text/plain"}) object which can contain arbitrary data, which we then get an URL by using the URL.createObjectURL(blob) method. The returned URL object can be set as a href attribute for a link (like we did in the examples above). Because your browser would normally just open the link, we have used the download="myfile.xyz" attribute. With this attribute you force the browser to download a linked document with the defined filename.

All of this is pretty smooth sailing when you're after text content (except some custom code for IE). Binary content is a slightly harder, because you don't want the Blob to do something with encoding on it. Therefore, we have to use one of the Typed Arrays (we used Uint8Array, an 8-bit unsigned integer array). A typed array is a view on the ArrayBuffer, which contains the actual binary data. We can use this ArrayBuffer to create a binary file like this: new Blob(buffer, {"type" : "image/gif"}).

One more thing: in the example above we directly access the chosen file from the input element. This was really easy: all we did was access the inputElement.files array (you did know we could do multiple file selects nowadays, didn't you?) and created an URL for the first element with URL.createObjectURL(inputElement.files[0]). This URL we assigned to the video.src attribute, Bob's (not Blob) your uncle!

So how handy is it, really?

Pretty damn handy. We didn't even scratch the surface of all the cool stuff you could do with this. Simply put, this API really makes working with files a whole lot easier. We can generate them, link them, and directly read them in the browser. Many things that required server-side processing can now be done on the client-side.

What else could we do with this?

  • Build a photo-editor in the browser without storing anything on the server
  • Resize uploaded images before we send them to the server

Great, but can I use it today?

Support isn't too bad (not too great, either, though). The only ones who have trouble with this are Safari and Opera. Safari seems not to like Blob URL's, and Opera does not support Blob URLs at all. IE wouldn't be IE if it wasn't a tiny bit different. IE10 doesn't like creating binary Blobs directly, so we have to use the (deprecated) BlobBuilder API.

The only browser with full support for the download attribute is Chrome, but we used window.saveAs() to have it work in IE10. In other browsers, clicking the link just opens the file in the browser.

Hit me with the source!

Feel free to look around the differente source files we used for this example.