Glossary

FileReader

FileReader is an event-based browser object that reads the contents of a Blob or File into memory without blocking the page. It is defined by the W3C File API. You pick a read method, wait for the load event, then use the result property. The most searched method is readAsDataURL, which returns a base64 data URL such as data:text/plain;base64,aGkgw6k=.

How it works

A reader has a readyState: 0 EMPTY (no read started), 1 LOADING and 2 DONE. It also has result and error properties. The four read methods are:

  • readAsText(blob, encoding) gives a string. It uses the encoding label you pass, then a byte order mark if the data starts with one, then the charset in the blob's type, then falls back to UTF-8.
  • readAsArrayBuffer(blob) gives an ArrayBuffer of the bytes.
  • readAsDataURL(blob) gives a data URL. The spec uses the blob's type as the media type and omits it if empty.
  • readAsBinaryString(blob) gives a byte string. The spec prefers readAsArrayBuffer over it.

Events fire in a fixed order: loadstart, then progress roughly every 50 ms while data arrives, then load on success (or error or abort), then loadend. None of them bubble. If you call a read method while the state is LOADING, the browser throws an InvalidStateError. Calling abort() during a read sets result to null and fires abort and then loadend.

Because the API is callback-based, people wrap it in a Promise. Modern code often skips it: blob.text() and blob.arrayBuffer() return promises directly, and text() always decodes as UTF-8.

Node.js has no FileReader, so this example runs the equivalent on a Blob and builds the data URL by hand, which is the string readAsDataURL yields for a blob of type text/plain:

(async () => {
  const blob = new Blob(['hi é'], { type: 'text/plain' });
  const bytes = Buffer.from(await blob.arrayBuffer());
  console.log('data:' + blob.type + ';base64,' + bytes.toString('base64'));
  console.log(bytes, await blob.text());
})();

Output from Node 22.22.0:

data:text/plain;base64,aGkgw6k=
<Buffer 68 69 20 c3 a9> hi é

The text "hi é" is 5 bytes in UTF-8, and base64 turns them into 8 characters.

How do I read a file with FileReader?

Create a reader, set onload, then call a read method: reader.onload = () => use(reader.result); reader.readAsText(file). The result is only valid inside or after the load event, and it is null before that. For a Promise, wrap it: new Promise((ok, fail) => { r.onload = () => ok(r.result); r.onerror = () => fail(r.error); r.readAsText(f); }).

Common pitfalls

  • Reading result too early: reader.result is null until load fires. Do not read it right after calling readAsText.
  • Reusing one reader for parallel reads: a second read while LOADING throws InvalidStateError. Create one reader per file.
  • Using readAsDataURL for big files: base64 inflates data by about one third and keeps it all in memory. Prefer URL.createObjectURL(blob) for previews.
  • Assuming the data URL prefix is stripped: the result includes data:...;base64, at the start. Split on the comma before decoding.
  • Ignoring the error event: a missing or unreadable file reports through reader.error, such as NotReadableError, not an exception.
  • Expecting FileReader in Node or workers: Node has none, and workers use FileReaderSync instead.

Related terms

  • File API — the specification that defines FileReader.
  • Blob — the object a reader consumes.
  • Base64 — the encoding behind readAsDataURL results.
  • UTF-8 — the fallback encoding for readAsText.
  • Promise — how you wrap reader events, or skip them with blob.text().
  • Event loop — each reader event is queued as a task.

See also