JavaScript File and FileReader
In the modern web development landscape, handling files efficiently and securely is crucial. JavaScript, the backbone of client-side scripting, offers robust
Web apps regularly need to work with files the user picks: reading a text document, previewing an image before upload, or processing binary data in the browser. JavaScript handles this with two related interfaces. The File interface describes a single file (its name, size, and type), and the FileReader interface reads that file's contents asynchronously without ever sending it to a server.
This guide covers how to get a File from an <input>, read it with FileReader, and use the newer promise-based file.text() and file.arrayBuffer() methods. A File is a specialized kind of Blob, so most of what you learn here also applies to blobs; see the broader File API overview for the full picture.
Understanding the File Interface in JavaScript
The File interface represents a single file's data. Files usually come from an <input type="file"> element, a drag-and-drop operation, or the Clipboard API. Because a File extends Blob, it carries the file's content plus metadata about it.
Key Properties of the File Interface
name: The file name as a string, e.g."report.pdf".size: The file size in bytes (a number).type: The MIME type as a string, e.g."image/png". May be""if the browser can't determine it.lastModified: A timestamp (milliseconds since the Unix epoch) of when the file was last changed.
Getting files from an input
A file <input> exposes a files property — a FileList, which is array-like. Use event.target.files[0] for the first file, or set the multiple attribute and loop over files to handle several at once.
Example: Displaying File Information
Here's a simple way to display information about a file the user selects:
<input type="file" id="fileInput" />
<div id="fileInfo"></div>document.getElementById('fileInput').addEventListener('change', function(event) {
const file = event.target.files[0];
if (!file) return; // user cancelled the dialog
const modified = new Date(file.lastModified).toLocaleString();
const info = `File Name: ${file.name}<br>
File Size: ${file.size} bytes<br>
File Type: ${file.type || 'unknown'}<br>
Last Modified: ${modified}`;
document.getElementById('fileInfo').innerHTML = info;
});Leveraging the FileReader API
The FileReader interface reads the contents of a File or Blob asynchronously. You start a read with one of its readAs… methods, then handle the result through events — the actual data never blocks the main thread.
FileReader Methods
readAsText(file): Reads the file as a text string (optionally with a given encoding).readAsDataURL(file): Reads the file as a base64-encoded data URL — handy for<img src>previews.readAsArrayBuffer(file): Reads the file as anArrayBufferof raw bytes for binary processing.
FileReader Events
Because reading is asynchronous, you attach handlers before calling a readAs… method:
onload: Fires when the read completes successfully; the data is inreader.result(also available asevent.target.result).onerror: Fires if the read fails; inspectreader.error.onprogress: Fires periodically during the read;event.loadedandevent.totallet you show a progress bar for large files.
Example: Reading a Text File
The following example reads a text file with FileReader and shows its contents, including a progress percentage:
<input type="file" id="textInput" />
<div id="textOutput">Upload a text file please</div>document.getElementById('textInput').addEventListener('change', function(event) {
const file = event.target.files[0];
if (!file) return;
const output = document.getElementById('textOutput');
const reader = new FileReader();
reader.onprogress = function(e) {
if (e.lengthComputable) {
const percent = Math.round((e.loaded / e.total) * 100);
output.textContent = `Reading… ${percent}%`;
}
};
reader.onload = function(e) {
output.textContent = e.target.result;
};
reader.onerror = function() {
output.textContent = 'Error reading file: ' + reader.error;
};
reader.readAsText(file);
});Advanced File Reading: Handling Different Data Types
Reading Images as Data URLs
To display an image file selected by the user, you can read it as a Data URL using the readAsDataURL method. This method encodes the file as a base64 encoded string, which can be used directly in image elements.
Example: Displaying an Image
<input type="file" id="imageInput" />
<div>Select an image file, please.</div>
<img id="imageDisplay" />document.getElementById('imageInput').addEventListener('change', function(event) {
const file = event.target.files[0];
const reader = new FileReader();
reader.onload = function(e) {
document.getElementById('imageDisplay').src = e.target.result;
};
reader.onerror = function() {
document.getElementById('imageDisplay').style.display = 'none';
alert('Error reading image file.');
};
reader.readAsDataURL(file);
});Reading Binary Files with ArrayBuffer
For applications that need to process audio, video, or any binary data, reading the file as an ArrayBuffer is essential. This method provides a generic buffer of binary data, which can be manipulated or passed to other APIs like Web Audio or WebGL.
Example: Processing Binary Data
<input type="file" id="binaryInput" />
<div id="binaryOutput">Select any file.</div>document.getElementById('binaryInput').addEventListener('change', function(event) {
const file = event.target.files[0];
const reader = new FileReader();
reader.onload = function(e) {
const buffer = e.target.result;
// Process the binary data
const info = `Buffer Length: ${buffer.byteLength} bytes`;
document.getElementById('binaryOutput').innerHTML = info;
};
reader.onerror = function() {
document.getElementById('binaryOutput').innerHTML = 'Error reading binary file.';
};
reader.readAsArrayBuffer(file);
});The Modern Way: file.text() and file.arrayBuffer()
FileReader predates promises, so its event-based API can feel verbose. All modern browsers add promise-returning methods directly on File/Blob, letting you read with async/await:
file.text(): Resolves to the file's contents as a UTF-8 string.file.arrayBuffer(): Resolves to anArrayBufferof the raw bytes.file.stream(): Returns aReadableStreamfor processing very large files in chunks.
<input type="file" id="modernInput" />document.getElementById('modernInput').addEventListener('change', async function(event) {
const file = event.target.files[0];
if (!file) return;
try {
const text = await file.text();
console.log('First 100 characters:', text.slice(0, 100));
const buffer = await file.arrayBuffer();
const bytes = new Uint8Array(buffer);
console.log('Total bytes:', bytes.length);
console.log('First byte:', bytes[0]);
} catch (err) {
console.error('Could not read file:', err);
}
});Prefer these promise methods for new code — they integrate cleanly with async/await and try/catch. Reach for FileReader when you need onprogress events or must support a very old browser. For sending files to a server in resumable chunks, combine file.slice() with these reads — see resumable file upload.
Conclusion
The File interface tells you about a file (name, size, type, lastModified), while FileReader and the newer file.text() / file.arrayBuffer() promises let you read its contents without a round-trip to the server. Together they cover the common needs: showing file metadata, previewing images, parsing text, and processing binary data entirely in the browser.
To go further, explore the related Blob type that File builds on and the broader File API.