cf.completefrontendCode editorOpen lab
THE JAVASCRIPT FIELD GUIDE

Files & Blobs

Read, create, preview, and download browser files with Blob, File, FileReader, object URLs, and drag-and-drop without uploading private data.

By the end you can
  • 01
    Explain Blob and FileTreat file data as bytes, labels, names, and last-modified metadata.
  • 02
    Read and preview safelyChoose text, bytes, streams, FileReader events, and object URLs for realistic UI jobs.
  • 03
    Handle local filesUse file inputs and drop zones while respecting privacy, cleanup, and browser limits.

Boxes of bytes the browser can hold

Web apps often need to work with local or generated files: preview an image before upload, export a CSV report, let a drawing app download a PNG, inspect a dropped text file, or store a draft for later. The browser gives JavaScript two central objects for this work: Blob and File.

A Blob is a sequence of bytes with a MIME type label. A File is a Blob with file metadata such as a name and a last-modified time. You do not get to browse the visitor’s disk. The user must choose or drop files, and even then the browser exposes the filename, not the full private path.

The short version

Use Blob methods such as text(), arrayBuffer(), stream(), and slice() to read or split bytes. Use object URLs when an element needs a URL for those bytes. Use FileReader when you need old-style events like progress and abort.

Real-life analogyA Blob is a sealed box

Imagine a box of parts sealed with tape. The outside label says what the sender claims it is. You can weigh the box, cut a smaller piece from it, or hand it to someone else. To see the parts, someone has to open it. Blob APIs work the same way: metadata is cheap, reading bytes is a separate action.

In real life: A sealed box
In JavaScript: A Blob: bytes you cannot see until you read them
In real life: A label saying “text/plain”
In JavaScript: The Blob’s type string
In real life: Cutting off one corner of the box
In JavaScript: blob.slice(start, end)
In real life: Opening the box
In JavaScript: text(), arrayBuffer(), stream(), or FileReader

Where the analogy stops: A real box proves what is inside when you open it. A Blob’s type label is not proof; code can put any label on any bytes.

This lesson builds that mental model, then turns it into browser UI: a Blob builder, a FileReader event replay, a progress reader, and a local file inspector with drag-and-drop.

Blob and File

CORE MODEL

Blob stands for “binary large object,” but the everyday meaning is simpler: some bytes JavaScript can pass around. A Blob may contain text, JSON, an image, a ZIP file, audio, or bytes you made yourself. It has two always-available properties: size in bytes and type, a MIME label like text/plain or an empty string.

A File is more specific. It is what a file input or drop zone usually gives you. It has every Blob ability, plus name and lastModified. That means any function that accepts a Blob can accept a File too.

Blob and File compared
QuestionBlobFile
What it representsBytes plus a type labelA Blob plus file metadata
Extra metadataOnly size and typeAlso name and lastModified
Created bynew Blob([...]), Response.blob(), canvas exportsFile inputs, drag-and-drop, or new File([...], name)
Can be read withtext(), arrayBuffer(), stream(), FileReaderThe same methods, because File extends Blob

The type string deserves respect and suspicion. It helps pick a preview strategy, but it is not verified by the browser. A text file can be mislabeled. A user’s operating system can report an empty type. A malicious upload can lie. Treat client-side labels as hints and validate important files on the server.

Build a Blob and read it back

INTERACTIVE

Let’s create a Blob from text. Strings become bytes when they are added to a Blob. The browser encodes them, usually as UTF-8. That is why a string’s length and a Blob’s size can differ: accents and emoji need more than one byte.

Blob builder: make a byte box
Blob builder sketchPop out in the code editor (opens in a new tab)JavaScript
const text = "Hello, café 🌍";const blob = new Blob([text], { type: "text/plain" });console.log(text.length);console.log(blob.size);console.log(blob.type);console.log(await blob.text());console.log([...new Uint8Array(await blob.arrayBuffer())].slice(0, 8));console.log(await blob.slice(7, 12).text());
Blob facts17 bytes
String length
14
Blob size
17 bytes
Type label
text/plain
Slice preview
Build to read slice

First bytes: Build to call arrayBuffer()

Text read back: Build to await blob.text()

Try it yourself

Type text, especially accented letters or the globe emoji, then build. The type is only a label; the bytes are whatever text you supplied.

Everything happens in this page. The object URL is revoked when you reset or leave the lesson.

Try café, then try hello, then add the globe character from the starter text. The string length tells you about JavaScript’s string representation; blob.size tells you how many bytes are in the sealed box. For the deeper string side, see Unicode and string internals.

The builder also reads the same Blob in three different ways: text() turns it back into a string, arrayBuffer() reveals bytes, and slice() creates a smaller Blob from a byte range. None of those changes the original Blob.

Object URLs: temporary tickets for bytes

PREVIEW

Many browser elements need URLs. An image preview wants an src. A download link wants an href. A video player wants a source. A Blob is not a URL, so the browser lets you ask for a temporary one with URL.createObjectURL(blob).

Real-life analogyAn object URL is a download link

A download link points to a file without putting the whole file in the link text. An object URL works the same way: it is a short reference, not a base64 copy of every byte.

In real life: A file on your computer
In JavaScript: The Blob or File kept by the browser
In real life: The download link
In JavaScript: The temporary blob: URL
In real life: Opening the link
In JavaScript: An element loading src or href
In real life: Removing the link
In JavaScript: URL.revokeObjectURL(url)

Where the analogy stops: A normal download link can point to the internet. An object URL points to bytes in this document and can be revoked early.

Create and revoke a download URLPop out in the code editor (opens in a new tab)JavaScript
const blob = new Blob(["download me"], { type: "text/plain" });const url = URL.createObjectURL(blob);link.href = url;link.download = "note.txt"; // Later, when the preview or link is no longer needed:URL.revokeObjectURL(url);

Keep object URLs only while the page needs them. When a preview is replaced, a Reset button clears it, or a React component unmounts, revoke the old URL. That cleanup tells the browser it may release the underlying bytes. Do not revoke immediately before an image has loaded or a click has used the link.

Object URLs are different from data URLs. A data URL embeds base64 text directly in the URL and is often about one third larger. FileReader’s readAsDataURL() can create one, but object URLs are usually better for previews and downloads.

FileReader: an older delivery tracker

STEP THROUGH

Modern Blob methods are promise-based: await blob.text() gives you the whole text, and await blob.arrayBuffer() gives you the bytes. FileReader is older. You create a reader, attach event listeners, then start a read with methods such as readAsText(), readAsArrayBuffer(), or readAsDataURL().

Real-life analogyFileReader is an older delivery tracker

An older delivery tracker gives you updates as a package moves. FileReader does the same with events for progress, abort, and errors.

In real life: Tracking starts
In JavaScript: loadstart
In real life: The progress bar moves
In JavaScript: progress
In real life: The delivery finishes
In JavaScript: load
In real life: Tracking closes either way
In JavaScript: loadend

Where the analogy stops: A real tracker can be late or wrong. FileReader events are asynchronous, and their progress counts vary.

Model FileReader event order
Step 0 of 13Ready
Your turn: follow the blue line

Switch the setting, predict the event order, then step through the modeled FileReader run.

Running in
  1. script
Next: line 1
Click the blue line to take the next stepPop out in the code editor (opens in a new tab)JavaScript
const reader = makeReader("success"); reader.addEventListener("loadstart", () => events.push("loadstart"));reader.addEventListener("progress", () => events.push("progress"));reader.addEventListener("load", () => events.push("load"));reader.addEventListener("abort", () => events.push("abort"));reader.addEventListener("error", () => events.push("error"));reader.addEventListener("loadend", () => events.push("loadend")); reader.readAsText(blob);console.log(events.join(" -> "));
CallStoreChangeResultRun = next line. Ran = already executed.
Recent returnsNothing yet. Start with the blue line.
Choose the read path

This is a pure model of FileReader event order. Real progress event counts vary by browser and file size.

A guided replay recorded from real JavaScript calls, not an engine debugger. Step follows executed statements; Back reviews a snapshot. Reset starts a fresh run.

On success you normally see loadstart, some number of progress events, load, and loadend. If the read is aborted, abort happens before the final loadend. If it fails, error happens before loadend. For basic whole-file reads, promises are easier; for visible progress, FileReader still has a job.

Progress demo: read generated bytes
Progress sketchPop out in the code editor (opens in a new tab)JavaScript
const blob = new Blob([largeBuffer], { type: "application/octet-stream" });const reader = new FileReader(); reader.addEventListener("progress", (event) => {  if (event.lengthComputable) {    console.log(Math.round((event.loaded / event.total) * 100) + "%");  } else {    console.log(event.loaded + " bytes read");  }}); reader.addEventListener("load", () => console.log(reader.result.byteLength));reader.readAsArrayBuffer(blob);
Progress logidle
  1. 1Press Read generated Blob. No local file is touched.
Try it yourself

FileReader reports progress events while it reads. Browsers decide chunk sizes, so you may see one event or several. The generated Blob is local to this page.

The test model predicts milestones such as 25%, 50%, 75%, 100%; real browser events are allowed to vary.

Inspect files from an input or a drop zone

INTERACTIVE

A file input and a drop zone both put File objects in your hands after the user chooses to share them with the page. The page can then inspect metadata, read the bytes, or send the file later. Merely selecting or dropping a file does not upload it.

File inspector: local metadata and previews
Drop zone sketchPop out in the code editor (opens in a new tab)JavaScript
dropZone.addEventListener("dragover", (event) => {  event.preventDefault();}); dropZone.addEventListener("drop", async (event) => {  event.preventDefault();  const [file] = event.dataTransfer.files;  if (!file) return;   console.log(file.name, file.size, file.type, file.lastModified);  if (file.type.startsWith("image/")) {    preview.src = URL.createObjectURL(file);  } else if (file.type.startsWith("text/") || file.name.endsWith(".txt")) {    preview.textContent = (await file.text()).slice(0, 400);  }});
Local filenone yet
Drop a file here

No file selected yet.

Try it yourself

Choose a file or drop one here. Nothing is uploaded.

The browser gives this page File objects only after you choose or drop them. This playground never sends them over the network.

The important drag-and-drop detail is dragover. Calling event.preventDefault() there tells the browser your element is a valid drop target. In drop, event.dataTransfer.files contains the files. Some folder drops do not produce ordinary File objects, so a friendly file UI handles an empty list without crashing.

When you build real upload forms, combine these File objects with the ideas from FormData. When you store generated files or offline responses, compare the tools in Cache API and file storage.

Choose the right reading tool

SORT

Every file task asks a different question. Do you need text, exact bytes, a stream of chunks, a preview URL, a self-contained base64 URL, or progress events? Pick the API that matches the job instead of memorizing one “file reading” method.

Match tasks to file-reading tools
TaskGood toolWhy
TaskGood toolWhy
Read a text fileawait file.text()Short, modern, promise-based code.
Parse bytesawait file.arrayBuffer()Gives exact bytes for binary formats.
Show an image previewURL.createObjectURL(file)The browser decodes from a temporary URL without base64 expansion.
Show progress or abortFileReaderIt exposes progress, abort, error, and loadend events.
Process huge data in chunksblob.stream()Streams fit chunk-by-chunk pipelines.
Sort the file-reading tools
  • blob.text()
  • file.text()
  • blob.arrayBuffer()
  • blob.stream()
  • URL.createObjectURL(blob)
  • readAsDataURL(file)
  • FileReader progress events
  • <a download> with an object URL
Try it yourself
0 of 8 correct

Place each API or pattern under the job it is best suited for.

Choose a category for every card. You can change an answer at any time; Reset clears them all.

If blob.stream() looks interesting, the Streams and progress lesson explains chunk-by-chunk processing. This lesson’s main rule is simpler: whole text, whole bytes, stream chunks, preview URL, or events.

Where you will use this

PRACTICAL

Files and Blobs show up whenever a browser app touches user data without a page refresh. A few realistic patterns:

  • Client-side export: turn rows into CSV text, create a Blob, make an object URL, and attach it to an <a download>.
  • Preview before upload: use a File from an input, show images with an object URL, and show text with file.text().
  • Generated media: canvas and media APIs can produce Blobs that become downloads or previews.
  • Offline workflows: store file-shaped data in OPFS or IndexedDB, and cache network Responses for app shells.
Privacy rule

The browser never hands your page a full local path like /Users/ada/taxes/receipt.pdf. It gives you the file name and bytes only after a user action. That is by design.

Common pitfalls

HONEST EDGE CASES
  • “Blob size is string length.” No. Blob size is bytes after encoding. Text with accents or emoji proves the difference.
  • “The type proves the file format.” No. type is a label and can be empty or wrong.
  • “Selecting a file uploads it.” No. Uploading requires your code to send it, often with FormData and fetch.
  • “Object URLs clean themselves instantly.” They last until revoked or the document goes away. Revoke long-lived previews.
  • “FileReader is the only way to read files.” Modern Blob methods are usually simpler unless you need events.
  • “The browser exposes the full path.” It exposes the file name, not the private folder path.

Practice exercises

5 EXERCISES
Exercise 1 · Warm-upCharacters or bytes?

Predict the two console lines.

Starter codePop out in the code editor (opens in a new tab)JavaScript
const blob = new Blob(["café"], { type: "text/plain" });
console.log("café".length);
console.log(blob.size);

Answer, then press Check. Spacing and letter case don’t matter.

    Exercise 2 · Warm-upProve File is a Blob

    Run the code in a modern browser console or Node 22 and write the three outputs.

    Starter codePop out in the code editor (opens in a new tab)JavaScript
    const file = new File(["hello"], "hello.txt", { type: "text/plain", lastModified: 10 });
    console.log(file instanceof Blob);
    console.log(file.name);
    console.log(file.size);

    Answer, then press Check. Spacing and letter case don’t matter.

      Exercise 3 · PracticeFind the final FileReader event

      Which event should cleanup code listen for if it must run after any FileReader outcome?

      Answer, then press Check. Spacing and letter case don’t matter.

        Exercise 4 · PracticeFix the leaking preview

        A component creates a new image preview every time a user chooses a file. What method should it call for the previous preview URL?

        Answer, then press Check. Spacing and letter case don’t matter.

          Exercise 5 · ChallengeDesign a safe inspector

          Your UI wants to display where a dropped file came from. Can browser JavaScript show the full path?

          Answer, then press Check. Spacing and letter case don’t matter.

            Check your understanding

            8 QUESTIONS
            Lesson quiz · 8 questionsScore: first tries count
            1. Question 1 of 8What does Blob.size measure?

              Choose an answer to see the explanation.

            2. Question 2 of 8What does this Blob program print?

              Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
              const blob = new Blob(["café"], { type: "text/plain" });
              console.log("café".length);
              console.log(blob.size);

              Choose an answer to see the explanation.

            3. Question 3 of 8Which statement about type is true?

              Choose an answer to see the explanation.

            4. Question 4 of 8What does this File program print?

              Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
              const file = new File(["hello"], "hello.txt", { type: "text/plain", lastModified: 10 });
              console.log(file instanceof Blob);
              console.log(file.name);
              console.log(file.size);

              Choose an answer to see the explanation.

            5. Question 5 of 8When should you revoke an object URL?

              Choose an answer to see the explanation.

            6. Question 6 of 8Which FileReader order is the usual success path in this lesson's model?

              Choose an answer to see the explanation.

            7. Question 7 of 8Which tool is best for a simple text file read?

              Choose an answer to see the explanation.

            8. Question 8 of 8What must a drop zone do in dragover to receive a drop?

              Choose an answer to see the explanation.

            Key takeaways

            • A Blob is a byte box with a type label; a File is a Blob with a name and last-modified time.
            • Blob size is bytes, not string length. Unicode text makes that difference visible.
            • Use text(), arrayBuffer(), and stream() for modern reads; use FileReader for progress, abort, and legacy data URL flows.
            • Object URLs are temporary tickets for previews and downloads. Revoke them when they are no longer needed.
            • File inputs and drop zones never reveal full local paths and never upload by themselves.

            Final definition.
            Files and Blobs are browser objects that let JavaScript hold, inspect, read, preview, and download bytes chosen or generated in the page.

            Up next: Device & platform APIs.

            CompleteFrontend Clear concepts. Working examples.