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:
load,
which is fired when the file is loaded successfullyerror
, which is fired when the file failed to be read
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
:
readAsText()
readAsDataURL()
readAsArrayBuffer()
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.
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:
- creating a
FileReader
- then listening for when the
load
event happens (meaning the file reading session was successful) - then creating an
<img>
element and putting the image into thesrc
attribute as a data-url - finally, appending the created
img
to the<div>
container we created for the images
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.
abort
- a file read has been aborted (canceled)progress
- fired periodically during a readloadstart
/loadend
- can be used to trigger something at the beginning or the end of the loading of the file
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.
- FileReader API (MDN)
- How to Read and Process Files with JavaScript FileReader API (DigitalOcean)
- File API (MDN)
- Blob API (MDN)
Claire selected Chicago Women's Health Center for an honorary donation of $50
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.