File handling lets web apps work with files the user chooses—text notes, images, CSV exports, and more. This tutorial covers the browser File API, FileReader, validation, security basics, and five hands-on examples you can run in the Try-it editor.
01
Pick files
<input type="file">
02
Read text
readAsText
03
Preview images
readAsDataURL
04
Validate
Size & MIME checks
05
Handle errors
onerror events
06
Stay safe
Blob URL cleanup
Fundamentals
Introduction
JavaScript file handling is how you read and process files inside a web page or on a server. In the browser, users pick a file from their device; your script receives a File object and can inspect metadata or read the contents without reloading the page.
This guide focuses on client-side file handling with the File API and FileReader—the skills you need for previews, local parsing, and upload validation. We also touch on Node.js fs so you know where server-side reading and writing happens.
Concept
What Is File Handling in JavaScript?
File handling means working with file data programmatically: reading text, previewing images, checking size limits, or preparing a file for upload. In the browser, JavaScript never gets free access to the user’s hard drive—the user must choose each file through a trusted picker or drag-and-drop zone.
Once selected, a File extends Blob with a name and lastModified date. You read bytes with FileReader or modern promise helpers like file.text() and file.arrayBuffer().
💡
Beginner Tip
Think of File as a handle to the user’s document and FileReader as the tool that opens it and hands you the contents when ready.
Key Features
User-driven access — files come from explicit user action, not silent disk scans.
Asynchronous reads — large files load in the background so the page stays responsive.
Text and binary — read plain text, base64 data URLs, or raw ArrayBuffer bytes.
Form integration — pair with <input type="file"> and optional drag-and-drop.
Client-Side vs Server-Side
Browser (File API) — read files locally for preview or validation before upload.
Node.js (fs) — read and write files on the server filesystem; never expose raw server paths to the client.
Foundation
Usage — File Input and FileReader
Start with an HTML file picker, then listen for the change event:
event.target.files is a FileList. Index 0 is the first selected file. Metadata is available immediately; you only need FileReader when you want the actual bytes or text inside the file.
📈 Practical Patterns
Read contents, preview media, and validate before processing.
Example 2 — Read a Text File with FileReader
Display the contents of a plain-text file in a <pre> element.
Hello from my notes file!
Line two of the document.
How It Works
readAsText decodes the file as UTF-8 text. When the read finishes, onload fires and event.target.result holds the full string. For modern browsers you can also write output.textContent = await file.text() inside an async handler.
Example 3 — Preview an Image with readAsDataURL
Turn an image file into a data URL and assign it to an <img> element for instant preview.
The <img> element displays the selected photo before upload.
How It Works
readAsDataURL produces a string like data:image/png;base64,… that browsers can load directly as an image source. Alternatively, preview.src = URL.createObjectURL(file) is faster for large files—just remember to revoke the URL when done.
Example 4 — Validate File Size and Type
Reject files that are too large or not plain text before spending time reading them.
JavaScript
const MAX_BYTES = 1024 * 1024; // 1 MB
function validateFile(file) {
if (file.size > MAX_BYTES) {
return "File is too large. Max size is 1 MB.";
}
if (!file.type.startsWith("text/") && !file.name.endsWith(".txt")) {
return "Only plain text files are allowed.";
}
return null; // valid
}
fileInput.addEventListener("change", (event) => {
const file = event.target.files[0];
if (!file) return;
const error = validateFile(file);
if (error) {
status.textContent = error;
fileInput.value = "";
return;
}
status.textContent = "Valid file: " + file.name;
});
Valid file: readme.txt
File is too large. Max size is 1 MB.
Only plain text files are allowed.
How It Works
Client-side checks improve UX by giving instant feedback. They are not a security boundary—always validate again on the server before trusting uploaded content.
Example 5 — Text File Viewer with Error Handling
A complete mini viewer: pick a .txt file, show its contents, and surface read errors gracefully.
Reading diary.txt…
(then full file text appears in <pre>)
How It Works
Hooking onerror and onabort prevents silent failures. Showing a loading message before readAsText gives users feedback while large files decode.
Applications
🚀 Common Use Cases
Image upload preview — show a thumbnail before sending to the server.
CSV / JSON import — parse local data files without a round trip.
Resume or document picker — validate PDF size and type on the client.
Drag-and-drop zones — accept dataTransfer.files from drop events.
Client-side compression — read bytes with ArrayBuffer before upload.
Offline tools — notepad-style apps that never leave the browser until export.
Watch Out
Important Considerations
No silent disk access — users must pick files; never assume a path.
Client validation ≠ security — re-check type, size, and content on the server.
Large files — reading multi-megabyte files into memory can freeze weak devices; consider chunking or streaming on the server.
Empty MIME types — some OS files report file.type === ""; fall back to extension checks.
Memory leaks — revoke blob URLs with URL.revokeObjectURL when previews change.
Sensitive data — treat file contents as user data; avoid logging secrets to the console in production.
🧠 How Browser File Reading Works
1
User selects file
The browser opens a picker. JavaScript receives a File reference in the change handler.
Picker
2
Optional validation
Check size, type, and extension before reading bytes.
Guard
3
Start async read
Call readAsText, readAsDataURL, or file.text(). The main thread stays free.
Read
4
📄
Use the result
Display text, set an image src, parse JSON, or append to FormData for upload.
Important
📝 Notes
accept on the input filters the picker UI but can be bypassed—always validate in code.
multiple attribute allows selecting many files; loop over files or use [...files].
Reset the input with fileInput.value = "" so the same file can be picked again.
FileReader is one-shot; create a new instance or call another read method for the next file.
Node.js fs.readFile / fs.promises.readFile run on the server, not in the browser tab.
For downloads, combine new Blob([data]) with a temporary <a download> link.
Compatibility
Browser Support
The File API and FileReader are widely supported in all modern browsers. Promise helpers like Blob.prototype.text() arrived later—check targets if you support very old engines.
✓ Baseline · File API
File API & FileReader
Supported in Chrome, Firefox, Safari, Edge, and current mobile browsers. Internet Explorer 10+ had partial FileReader support; IE is obsolete for new projects.
98%Modern browser support
Google ChromeAll versions · Desktop & Mobile
Full support
Mozilla FirefoxAll versions · Desktop & Mobile
Full support
Apple SafariAll versions · macOS & iOS
Full support
Microsoft EdgeAll versions · Chromium & Legacy
Full support
Internet ExplorerIE 6+ · Legacy environments
Full support
OperaAll modern versions
Full support
FileReaderExcellent
Bottom line: Safe for production web apps targeting evergreen browsers. Use feature detection (if (window.FileReader)) only if you must support legacy embedded WebViews.
Wrap Up
Conclusion
JavaScript file handling in the browser starts with user-selected files, continues with metadata checks, and finishes by reading contents through FileReader or modern promise helpers. With validation and error handlers in place, you can build previews, importers, and upload flows that feel instant and trustworthy.
Practice the five examples above, then explore array and string methods to process the text you read from files.
Expect to write arbitrary paths on the user’s disk from the browser
Summary
Key Takeaways
Knowledge Unlocked
Five things to remember about file handling
Your foundation for client-side files in JavaScript.
5
Core concepts
📁01
User picks
<input type="file">
Access
📄02
Metadata
name, size, type.
Inspect
📖03
Read text
readAsText.
Content
🖼04
Preview
readAsDataURL.
Images
⚠05
Validate
Size + type checks.
Safety
❓ Frequently Asked Questions
No. In the browser, JavaScript can only access files the user explicitly selects through an input type=file element, drag-and-drop, or the File System Access API (where supported). It cannot browse arbitrary folders on the disk.
A File object represents the selected file (name, size, type). FileReader is a helper that reads the File contents asynchronously and delivers the result through onload, onerror, and onabort events.
Use readAsText (or the modern file.text() promise) for plain text files like .txt, .csv, or .json. Use readAsDataURL when you need a base64 data URL—most often to preview images in an img src attribute.
Not to arbitrary paths on the user's disk. You can trigger downloads with Blob and URL.createObjectURL, or use the File System Access API in supported browsers when the user grants save permission. Server-side Node.js uses fs to read and write on the server.
Check file.size and file.type (MIME) in your change handler before reading. Use the accept attribute on the input to hint allowed types, but always re-validate because accept is not a security boundary.
Blob URLs stay in memory until revoked. After you finish previewing or downloading, call URL.revokeObjectURL(url) to free memory—especially important when users pick many files in one session.
Did you know?
Every File is also a Blob, so you can pass it directly to fetch bodies, FormData.append, or URL.createObjectURL without reading it into a string first.