Dec 22

FileReader API

Asynchronously read and interpret an uploaded file, no back-end server required.

By Claire Lipskey

Ever wonder how websites claim to interpret an uploaded file without storing any of your data? Admittedly, I used to be a bit skeptical myself. Enter the FileReader API! It allows a client-side application to asynchronously read and interpret an uploaded file.

In order to do this in your own client-side application, you'll also want to learn about the File API and/or the Blob API. These are the objects that you'll read with the FileReader API. You can also use the FileReader API to analyze files from a drag-and-drop operation.

Although this API has been around for a while (Chrome started supporting it in version 6), parts of the modern usage haven't been supported as long, such as the File API (shipped in Chrome 13) and the File() constructor (shipped in Chrome 38).

In an almost ironic move, to test this API locally, you must serve the JavaScript from a secure domain (HTTPS), which can be done with several local tools or something like Codepen.

The Basics

The FileReader API, in basic usage, can be used in conjunction with <input type="file" />. Once a file is either selected through the file browser or dragged and dropped onto the file field, a new File object is created on the input element.

FileReader can be used with any File object, but we’ll explore a basic usage scenario.

Let's try to pass the File object to the FileReader API like so:

function readFile(file) {
const fileReader = new FileReader();
fileReader.readAsText(file);
}

The above sample is not quite complete, however. The FileReader API is asynchronous by default and does not use promises. Instead, there are several events you can listen to.

For now, let's focus on the following:

function readFile() {
const fileReader = new FileReader();
const resultContainer = document.getElementById('result');
const file = document.getElementById(‘uploaded-file’).files[0];

if (file) {
fileReader.readAsText(file);
}

fileReader.addEventListener('load', () => {
resultContainer.innerText = fileReader.result
}, { once: true })
}

Notice in the above example that we’re setting the text of the resultContainer to the result that the FileReader got once it fired the load event.

result on the fileReader object is exactly what you'd expect: whatever the FileReader read from the file is contained in the result property.

While it's not able to read every type of file's contents, the following methods are available for FileReader:

I'll go through the first two in this article but know that this is a powerful API for a wide variety of applications.

Method: readAsText()

First up is the very basic text method FileReader API allows us to use. You'll want only to use this method for smaller files, as it reads the entire file into memory. For larger files, you'll want to use readAsArrayBuffer(), as it returns a promise and is more predictable with larger files.

In the example above, we take the file we give readFile() and log the result of the readAsText method. This can be very useful if we want to interpret any kind of text-based file, such as .txt, .csv, etc.

See the CodePen.

Method: readAsDataURL()

This method can be used for reading images, similar to how you'd interact with images if they were data-url strings. That is exactly what this method does: returns the image as a base64 encoded data-url.

Note: It is readAsDataURL - with URL all uppercase - not readAsDataUrl. Using the latter will cause an error - it is case-sensitive.

Let's take the example below:

<!-- Don't forget to write HTML semantically! -->
<label>
<input type="file" id="uploaded-file" onchange="readImage()" name="uploaded-file" accept="image/*">
Upload an image.
</label>
<div id="result"></div>

Notice I am using the accept attribute to limit the uploaded file to a MIME-type that is a type of image. Review how to specify file types to be accepted on MDN.

function readImage() {
const fileReader = new FileReader();
const file = document.getElementById("uploaded-file").files[0];

if (file) {
fileReader.readAsDataUrl(file);
}

fileReader.addEventListener('load', () => {
const result = fileReader.result;
const resultContainer = document.getElementById("result");
const img = document.createElement("img");
img.src = result;
resultContainer.append(img);
}, { once: true })
}

In the above example, we're:

  1. creating a FileReader
  2. then listening for when the load event happens (meaning the file reading session was successful)
  3. then creating an <img> element and putting the image into the src attribute as a data-url
  4. finally, appending the created img to the <div> container we created for the images

See the CodePen.

This API is great for simplistic things like in-browser manipulation or even real-time status updates while uploading the image / text / whatever the file might be to the backend server. Updating your profile picture on a major social network? You could replicate that with the FileReader API.

FileReader Events

There are several other events on the FileReader that are good to know.

The events are extended from the ProgressEvent interface. By listening to the progress event on FileReader, you can calculate file read progress by dividing the loaded by the total properties on the ProgressEvent.

fileReader.addEventListener("progress", (event) => {
const progress = (event.loaded / event.total) * 100;
console.log(`Read progress: ${progress}%`);
});

Further Reading

FileReader is a great API that can be used for many client-side applications. It’s an underpinning of a lot of applications you might already use. 

Claire Lipskey

Claire Lipskey

Claire is a front-end focused engineer passionate about standards-based solutions to the web’s problems. She lives in Chicago with her wife, elder cat and golden retriever puppy.

Claire selected Chicago Women's Health Center for an honorary donation of $50

Chicago Women's Health Center

CWHC has practiced an approach to care that affirms clients and students, and ensures they have access to the information they need to decide what is best for their health and right for their bodies.