Using files from web applications

Using the File API, which was added to the DOM in HTML5, it's now possible for web content to ask the user to select local files and then read the contents of those files. This selection can be done by either using an HTML <input> element or by drag and drop.

If you want to use the DOM File API from extensions or other browser chrome code, you can; however, note there are some additional features to be aware of. See Using the DOM File API in chrome code for details.

Note that in this case, the handleFiles() function itself is the event handler, unlike previous examples where it was called by an event handler which passed it a parameter.

注意在这个例子里，handleFiles() 方法本事是一个事件处理器，不像之前的例子中，它被事件处理器调用然后传递给它一个参数。

Getting information about selected file(s)

获取被选择文件的信息

The FileList object provided by the DOM lists all of the files selected by the user, each specified as a File object. You can determine how many files the user selected by checking the value of the file list's length attribute:

Using hidden file input elements using the click() method

通过click()方法使用隐藏的file input元素

Starting in Gecko 2.0 (Firefox 4 / Thunderbird 3.3 / SeaMonkey 2.1), you can hide the admittedly ugly file <input> element and present your own interface for opening the file picker and displaying which file or files the user has selected. You can do this by styling the input element with display:none and calling the click() method on the <input> element.

We don't actually need to do anything with the dragenter and dragover events in our case, so these functions are both simple. They just stop propagation of the event and prevent the default action from occurring:

Here, we retrieve the dataTransfer field from the event, pull the file list out of it, and then pass that to handleFiles(). From this point on, handling the files is the same whether the user used the input element or drag and drop.

Example: Showing thumbnails of user-selected images

例子：显示用户选择的图片的缩略图

Let's say you're developing the next great photo-sharing website and want to use HTML5 to display thumbnail previews of images before the user actually uploads them. You can establish your input element or drop zone as discussed previously and have them call a function such as the handleFiles() function below.

Here our loop handling the user-selected files looks at each file's type attribute to see if it's an image file (by doing a regular expression match on the MIME type string pattern "image/*"). For each file that is an image, we create a new img element. CSS can be used to establish any pretty borders or shadows and to specify the size of the image, so that doesn't need to be done here.

Each image has the CSS class obj added to it, making it easy to find in the DOM tree. We also add a file attribute to each image specifying the File for the image; this will let us fetch the images for actual upload later. We use Node.appendChild() to add the new thumbnail to the preview area of our document.

Next, we establish the FileReader to handle asynchronously loading the image and attaching it to the img element. After creating the new FileReader object, we set up its onload function and then call readAsDataURL() to start the read operation in the background. When the entire contents of the image file are loaded, they are converted into a data: URL which is passed to the onload callback. Our implementation of this routine sets the img element's src attribute to the loaded image which results in the image appearing in the thumbnail on the user's screen.

Using object URLs

使用对象URL

Gecko 2.0 (Firefox 4 / Thunderbird 3.3 / SeaMonkey 2.1) introduces support for the DOM window.URL.createObjectURL() and window.URL.revokeObjectURL() methods. These let you create simple URL strings that can be used to reference any data that can be referred to using a DOM File object, including local files on the user's computer.

The object URL is a string identifying the File object. Each time you call window.URL.createObjectURL(), a unique object URL is created even if you've created an object URL for that file already. Each of these must be released. While they are released automatically when the document is unloaded, if your page uses them dynamically you should release them explicitly by calling window.URL.revokeObjectURL():

This establishes our file <input> element as well as a link that invokes the file picker (since we keep the file input hidden to prevent that less-than-attractive user interface from being displayed). This is explained in the section Using hidden file input elements using the click() method, as is the method that invokes the file picker.

Set up the image's load event handler to release the object URL since it's no longer needed once the image has been loaded. This is done by calling the window.URL.revokeObjectURL() method and passing in the object URL string as specified by img.src.

Example: Uploading a user-selected file

Another thing you might want to do is let the user upload the selected file or files (such as the images selected using the previous example) to a server. This can be done asynchronously very easily.

Creating the upload tasks

Continuing with the code that built the thumbnails in the previous example, recall that every thumbnail image is in the CSS class obj with the corresponding File attached in a file attribute. This allows us to select all of the images the user has chosen for uploading using Document.querySelectorAll(), like this:

Line 2 fetches a NodeList, called imgs, of all the elements in the document with the CSS class obj. In our case, these will be all of the image thumbnails. Once we have that list, it's trivial to go through it and create a new FileUpload instance for each. Each of these handles uploading the corresponding file.

Handling the upload process for a file

The FileUpload function accepts two inputs: an image element and a file from which to read the image data.

The FileUpload() function shown above creates a throbber, which is used to display progress information, and then creates an XMLHttpRequest to handle uploading the data.

Before actually transferring the data, several preparatory steps are taken:

The XMLHttpRequest's upload progress listener is set to update the throbber with new percentage information so that as the upload progresses the throbber will be updated based on the latest information.

The XMLHttpRequest's upload load event handler is set to update the throbber progress information to 100% to ensure the progress indicator actually reaches 100% (in case of granularity quirks during the process). It then removes the throbber since it's no longer needed. This causes the throbber to disappear once the upload is complete.

The request to upload the image file is opened by calling XMLHttpRequest's open() method to start generating a POST request.

The MIME type for the upload is set by calling the XMLHttpRequest function overrideMimeType(). In this case, we're using a generic MIME type; you may or may not need to set the MIME type at all depending on your use case.

The FileReader object is used to convert the file to a binary string.

Finally, when the content is loaded the XMLHttpRequest function send() is called to upload the file's content.

Note: The non-standard sendAsBinary method which was previously used in the example above is considered deprecated as of Gecko 31 (Firefox 31 / Thunderbird 31 / SeaMonkey 2.28); use the standard send(Blob data) method instead.