The W3C File API

Introduction

In Opera 11.10, partial support for the W3C File API makes its debut. This spec “provides an API for representing file objects in web applications, as well as programmatically selecting them and accessing their data”. For example, you can upload files into the browser and find out information such as name, size and type without having to go to the server. You can also open the file and manipulate its contents. This can enhance interactivity of browser-based applications to make them more like desktop applications.

Getting some examples on file

Let’s build up a couple of simple examples. Assume you have a Content Management System that allows a user to upload images to your corporate website, and you want to ensure that they don’t upload uncompressed images. What we’ll do is use the File API to check that the file they upload isn’t larger than 128K.

The HTML is rudimentary:

<form>
    <input type="file" id="upload" name="files">
    <div id="message"></div>
    <input type="submit">
</form>

The blank message <div> is present so we can insert an error message into it if the file is too large. We’ll also disable the submit button if the file is too large. If the user doesn’t have script enabled, or is using a browser that doesn’t support this part of the File API, there is no error checking, so you’ll need to do it on the server. In fact, this is a good time to repeat the Infallible Mantra of Forms: Never, ever, ever rely on client-side validation or error checking. Always check on the server and sanitise the input. Always.

The script adds an event listener to the file upload field (id=input) so the checking function is called if the user selection changes:

document.getElementById('upload').addEventListener('change', doStuff, false);

The magical part is

var size = evt.target.files[0].size;

The API gives us an array of files, because HTML5 allows the multiple attribute on <input type=file>, but we only want the first element as we’re only allowing one upload for our example.

The size property is in bytes, so we test whether it exceeds 131072 (which is 128K) and, if so, we disable the submit button and offer a helpful error message:

document.getElementById('message').innerHTML = size + ' is too big, you numpty';
var submit = document.querySelector('input[type=submit]');
submit.disabled=true;

Try out our check size example.

We can check other things too, such as the name of a file and its last modification date (but you can’t rely on that to be present; the spec says “If user agents cannot make this information available, they MUST return the empty string”).

Also of interest is the file type. Let’s tweak our script to disable the submit button if the file type is not a PNG image:

var type = evt.target.files[0].type;

if (type != 'image/png') {
  message.innerHTML = type + ' is not a PNG, you dweeb';
  submit.disabled = true;
}

Here we compare the MIME type with the file’s type property to make sure we have the correct format that our CMS requires. It’s also important to note that, as with the last modification date, “If implementations cannot determine the media type of the Blob, they MUST return the empty string”, so in the case of an empty string you should allow upload to the server for further error checking there.

if (type == 'image/png' || type == '') {
  message.innerHTML = type + ' is a lovely type';
  submit.disabled = false;
}

Try out our check type example.

Remember the mantra never to trust client-side validation? If you rename evil-virus.exe to lovely-flowers.jpg, the File API will believe it’s an image. You don’t want to store that in your file system without checking it on the server first!

It’s also possible to open the file and use the contents using the File Reader API. For example, you could generate thumbnails of uploaded images and display them next to the form so a user would know at a glance which ones they’ve already uploaded from a directory. If you’re really clever, you could grab the artist and title information from an MP3 file — or even the album cover art!

Summary

This concludes our tour of the current Opera support for the W3C file API. Happy Filing!