Working with Files Using the FileReader API
When a user selects a file in your web app, you get a File object — but how do you actually read its contents? That’s where the JavaScript FileReader API comes in. This article walks through how FileReader works, when to use it, and how it compares to modern alternatives.
Key Takeaways
- The FileReader API reads
FileorBlobcontents asynchronously using one of three methods:readAsText(),readAsArrayBuffer(), orreadAsDataURL(). - FileReader uses an event-driven model with
load,error,progress, and other events to communicate results. - You can wrap FileReader in a Promise for cleaner integration with
async/awaitcode. - Modern
Blob.text()andBlob.arrayBuffer()methods are simpler for basic reads, but FileReader is still the right choice when you need progress tracking, non-UTF-8 encoding, or base64 data URLs.
What Is the FileReader API?
The FileReader API is a browser interface that reads the contents of File or Blob objects asynchronously. It cannot access arbitrary files on the user’s system by path — it only works with files the user has explicitly selected, either through <input type="file"> or a drag-and-drop interaction.
const input = document.querySelector('input[type="file"]')
input.addEventListener('change', () => {
const file = input.files[0]
console.log(file.name, file.size, file.type)
})
A File object inherits from Blob, so it carries the same properties plus name and lastModified. You pass it directly to any FileReader read method.
The Three Core Reading Methods
Reading local files in JavaScript with FileReader means choosing the right output format:
readAsText(file, encoding?)— Returns the file contents as a string. Defaults to UTF-8. Useful for CSV, JSON, plain text, or any text-based format.readAsArrayBuffer(file)— Returns raw binary data as anArrayBuffer. Use this for images, audio, PDFs, or any binary processing.readAsDataURL(file)— Returns a base64-encodeddata:URL. Convenient for image previews, but note the result is roughly 33% larger than the original file due to base64 encoding overhead.
Avoid
readAsBinaryString()— it’s deprecated. UsereadAsArrayBuffer()instead for binary data.
FileReader’s Event-Driven Model
FileReader is asynchronous and communicates through events. The key ones are:
| Event | When it fires |
|---|---|
loadstart | Reading begins |
progress | Fires periodically during read |
load | Read completed successfully |
error | Read failed |
loadend | Read finished (success or failure) |
Here’s a practical image preview before upload using readAsDataURL():
function previewImage(file) {
const reader = new FileReader()
reader.addEventListener('load', () => {
const img = document.querySelector('#preview')
img.src = reader.result
})
reader.addEventListener('error', () => {
console.error('Failed to read file:', reader.error)
})
reader.readAsDataURL(file)
}
The progress event is particularly useful for showing a progress bar with large files:
reader.addEventListener('progress', (event) => {
if (event.lengthComputable) {
const percent = Math.round((event.loaded / event.total) * 100)
progressBar.value = percent
}
})
Discover how at OpenReplay.com.
Wrapping FileReader in a Promise
FileReader’s callback style can feel awkward in modern async code. A simple wrapper fixes that:
function readFileAsText(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader()
reader.addEventListener('load', () => resolve(reader.result))
reader.addEventListener('error', () => reject(reader.error))
reader.readAsText(file)
})
}
// Usage
const text = await readFileAsText(file)
FileReader vs Blob.text() and Blob.arrayBuffer()
Modern browsers support promise-based methods directly on Blob (and therefore File):
// Modern approach — simpler for basic reads
const text = await file.text()
const buffer = await file.arrayBuffer()
So when should you still use FileReader? Choose it when you need:
- Progress tracking via the
progressevent (though for local files some browsers may fire only a small number of progress events) - Non-UTF-8 encoding support via
readAsText(file, 'ISO-8859-1') - Base64 data URLs via
readAsDataURL() - Broader legacy browser support
For straightforward text or binary reads in modern apps, Blob.text() and Blob.arrayBuffer() are cleaner. For image previews, URL.createObjectURL(file) avoids base64 expansion and is generally more memory-efficient than readAsDataURL(). Just remember to call URL.revokeObjectURL() when the object URL is no longer needed to avoid memory leaks.
Conclusion
The FileReader API remains a practical tool for working with File objects in the browser — especially when you need progress events, encoding control, or data URLs. For simpler cases, the newer Blob methods require less code. Know both, and you’ll handle any file-reading scenario cleanly.
FAQs
No. FileReader can only read files the user has explicitly selected through an input element or drag-and-drop interaction. The browser's security model prevents JavaScript from accessing arbitrary files on the filesystem by path. This restriction exists to protect user privacy and system security.
readAsArrayBuffer returns raw binary data suitable for processing or manipulation, such as parsing image metadata or audio waveforms. readAsDataURL returns a base64-encoded string you can use directly as an image src or CSS background. The data URL approach is convenient but produces output roughly 33 percent larger than the original file.
If you just need the text content and your app targets modern browsers, Blob.text() is simpler because it returns a Promise directly. Use FileReader when you need progress tracking for large files, need to specify a non-UTF-8 encoding, or need to support older browsers that lack the Blob.text() method.
If you use URL.createObjectURL to generate a preview URL, call URL.revokeObjectURL once the image has loaded or the preview is removed. If you use readAsDataURL instead, the base64 string is managed by garbage collection automatically, but it consumes more memory than an object URL for the same file.
Complete picture for complete understanding
Capture every clue your frontend is leaving so you can instantly get to the root cause of any issue with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data.
Check our GitHub repo and join the thousands of developers in our community.