File API

Course 3 · Ch 5
File API
Reading a file's contents entirely client-side — image previews, text parsing, and validation, all before anything uploads

Chapter 4 ended with dragged files landing in dataTransfer.files as a FileList — the exact same type a regular <input type="file"> (Intermediate Chapter 1) produces. This chapter covers what you can actually do with that File object once you have it, entirely in the browser, with no server round-trip required at all.

Getting Files from an Input

<input type="file" id="fileInput" accept="image/*"> <script> document.getElementById('fileInput').addEventListener('change', (event) => { const file = event.target.files[0]; // files is a FileList, even for a single file console.log(file.name, file.size, file.type); }); </script>
file.name
The original filename
file.size
Size in bytes
file.type
MIME type, e.g. "image/png"
file.lastModified
Timestamp of last modification
accept doesn't actually restrict what a user can select
The accept attribute only filters the OS file picker dialog's default view — most file pickers still let a user manually choose "All Files" and pick anything regardless. Always re-check file.type in JavaScript (and validate the actual file content server-side, never trust the client-reported type alone) rather than relying on accept as genuine validation.

FileReader — Reading the Actual Content

A File object alone only gives metadata — FileReader actually reads the bytes, asynchronously, in one of several formats depending on what's needed.

MethodReads the file as
readAsDataURL()A base64 data URL — directly usable as an <img> src, for instant previews
readAsText()Plain text — for .txt, .csv, .json files
readAsArrayBuffer()Raw binary data — for processing binary formats directly

A Real Example — Instant Image Preview Before Upload

document.getElementById('fileInput').addEventListener('change', (event) => { const file = event.target.files[0]; if (!file) return; const reader = new FileReader(); reader.onload = () => { const img = document.getElementById('preview'); img.src = reader.result; // the data URL, ready to display directly }; reader.readAsDataURL(file); });

This is exactly the pattern behind every "see a preview before you upload" experience — the user picks a file, sees it rendered instantly, and nothing has been sent to a server at all yet. The actual upload (if any) happens separately, typically via the FormData covered in Intermediate Chapter 10.

Reading Text Files — Client-Side CSV/JSON Preview

reader.onload = () => { const text = reader.result; try { const data = JSON.parse(text); console.log('Parsed JSON:', data); } catch (err) { console.error('Not valid JSON'); } }; reader.readAsText(file);

Drag-and-Drop + File API — Tying Chapters 4 and 5 Together

dropzone.addEventListener('drop', (event) => { event.preventDefault(); const file = event.dataTransfer.files[0]; // Chapter 4's dataTransfer.files const reader = new FileReader(); // Chapter 5's FileReader, same as a normal input reader.onload = () => { /* preview, parse, etc. — identical to above */ }; reader.readAsDataURL(file); });

Because a dragged file and a file selected via <input type="file"> both produce identical File objects, the exact same FileReader code handles both without any special-casing — a genuinely clean piece of API design that pays off whenever both interaction methods are offered together.

Reading a file client-side is never a substitute for server-side validation on upload
Everything in this chapter happens entirely in the user's own browser and tells you nothing trustworthy about what actually arrives at your server — a malicious user can trivially fabricate a request with completely different file content than whatever the client-side code displayed or validated. Treat client-side file reading purely as a UX convenience (instant previews, early format checks); always re-validate file type, size, and content again on the server before trusting or storing anything.

Chapter 5 Quick Reference

  • input.files — a FileList, even for a single file; access individual files by index
  • accept attribute doesn't enforce anything — just filters the picker's default view; always re-check file.type in JS
  • FileReader.readAsDataURL() — base64 data URL, directly usable as an img src for instant previews
  • readAsText() / readAsArrayBuffer() — for text content and raw binary data respectively
  • reader.onload fires asynchronously once reading completes; result available as reader.result
  • Drag-and-drop files and input-selected files produce identical File objects — the same FileReader code handles both
  • Client-side reading is UX only — server-side validation of every uploaded file remains essential regardless
  • Next chapter: Web Storage & offline — localStorage/IndexedDB, service workers intro