completefrontend
Open lab My progress
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 FileSay what a Blob holds (bytes and a type label) and what a File adds (a name and a last-changed time).
  • 02
    Read and preview filesPick the right tool for each job: text(), arrayBuffer(), stream(), FileReader events, or an object URL.
  • 03
    Work with the user's filesUse a file input and a drop zone, cancel object URLs you no longer need, and keep the user's folders private.

Bytes the browser can hold

A computer stores every file as bytes. A byte is a small number from 0 to 255. Text, pictures, and music are all just long rows of bytes.

Web pages often need to work with files. For example, a page may want to:

  • show a picture before you upload it,
  • save a table of scores as a file on your computer,
  • read a text file that you drop onto the page.

For this, the browser gives JavaScript two kinds of object: Blob and File.

  • A Blob holds some bytes and a type label, such as text/plain.
  • A File is a Blob with two more facts: a name and the time it was last changed.

Your page can't look around the visitor's computer. The visitor must pick a file or drop it onto the page. Even then, the page only learns the file's name, not the folder it came from.

The short version

To read the bytes in a Blob, use its methods: text(), arrayBuffer(), stream(), and slice(). When a page element needs a web address for the bytes, make an object URL. When you need to watch a read happen step by step, use FileReader.

Real-life analogyA Blob is a sealed box

Picture a box that is taped shut. A label on the outside says what is inside. You can weigh the box, cut a smaller piece off it, or hand it to someone. To see what is inside, someone has to open it. Checking the label is quick. Opening the box is a separate job.

In real life: A sealed box
In JavaScript: A Blob: bytes you can't see until you read them
In real life: A label that says “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

In this lesson you will try four small tools in the page:

  • a Blob builder that makes a Blob from your text,
  • a step-through that shows FileReader events in order,
  • a reader that shows progress while it reads,
  • a file inspector where you can pick or drop your own file.

Blob and File

CORE MODEL

Blob is short for "binary large object". In plain words, a Blob is some bytes that JavaScript can pass around. Those bytes can be text, JSON, a picture, a ZIP file, or sound.

Every Blob has two properties you can always read:

  • size: how many bytes it holds.
  • type: a MIME type, which is a short label for the kind of data, such as text/plain or image/png. It can also be an empty string.

A File is what you usually get from a file picker or a drop onto the page. A File can do everything a Blob can do. It also has two more properties:

  • name: the file name, such as hello.txt.
  • lastModified: when the file was last changed, as a number of milliseconds.

So any code that works with a Blob also works with a File.

Left: a Blob holds the text hello, with size 5 and type text/plain. Right: a File holds the same text, size, and type, plus a name tag that says hello.txt and time 10."hello"Blobsize: 5type: "text/plain""hello"Filesame size and typehello.txttime: 10+ name+ lastModified
A Blob holds bytes, a size, and a type. The File from exercise 2 holds the same things, plus a name and a lastModified time.

The table puts the two side by side. Read each row as one question about both.

Blob and File side by side
QuestionBlobFile
What does it hold?Bytes and a type label.The same, plus facts about the file.
Which properties does it have?Only size and type.Also name and lastModified.
Where does it come from?new Blob([...]), Response.blob(), or a canvas picture.A file input, a drop, or new File([...], name).
How do you read it?With text(), arrayBuffer(), stream(), or FileReader.With the same methods, because a File is a Blob.

Don't fully trust the type label. It helps you choose how to show a file, but the browser doesn't check it against the bytes:

  • A text file can have the wrong label.
  • The computer may give a file no label at all, so type is an empty string.
  • Someone who wants to cause harm can put a false label on a file on purpose.

Use the label as a hint in the page. When a file matters, the server must check it again.

Build a Blob and read it back

INTERACTIVE

Let's make a Blob from text. When text goes into a Blob, the browser turns each letter into bytes. It uses a system called UTF-8. In UTF-8, plain English letters take one byte each. Letters with accents, like é, take two bytes. An emoji, like the globe, takes four.

That is why a string's length and a Blob's size can be different numbers. length counts letters. size counts bytes.

Top row: the string café as 4 letters, c, a, f, é. Bottom row: the same text in a Blob as 5 bytes, 99, 97, 102, 195, 169. The letter é takes two bytes, 195 and 169."café".length4 letterscaféé takes 2 bytesblob.size5 bytes9997102195169
The string "café" has 4 letters. In a Blob it becomes 5 bytes, because é needs 2 bytes.
Blob builder: turn text into bytes
Make a Blob and read it three waysPop 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
Part of the Blob
Build to read a slice

First bytes: Build to call arrayBuffer()

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

Try it yourself

Type some text, then press Build Blob. Try letters with accents or the globe emoji. The type is only a label: the bytes are the text you typed.

Everything happens in this page. The object URL is cancelled when you press Reset or leave the lesson.

Try café, then hello, then put the globe from the starting text back in. The string length tells you how many letters JavaScript counts. blob.size tells you how many bytes are in the Blob. To learn more about how strings store letters, see Unicode and string internals.

The builder reads the same Blob in three ways:

  • text() turns the bytes back into a string.
  • arrayBuffer() gives you the raw bytes. An ArrayBuffer is a block of bytes; the code wraps it in a Uint8Array so it can print each byte as a number.
  • slice(start, end) makes a new, smaller Blob from part of the bytes.

text() and arrayBuffer() return promises: the answer comes a little later, so the code writes await to wait for it. None of these methods changes the original Blob.

A Blob can also be built from other Blobs. The code below joins two small Blobs into one.

Join Blob parts in orderPop out in the code editor (opens in a new tab)JavaScript
const header = new Blob(["Name,Score\n"], { type: "text/csv" });
const rows = new Blob(["Asha,9\n"], { type: "text/csv" });
const report = new Blob([header, rows], { type: "text/csv" });
console.log(report.type);
console.log(report.size);

Line 1 makes a Blob with the header line. Line 2 makes a Blob with one row. Line 3 puts both into a new Blob, in that order: header first, then the row. Line 4 prints text/csv. Line 5 prints 18, because the header has 11 bytes and the row has 7. The type is still only a label, so a server must check an uploaded report.

Object URLs: short web addresses for bytes

PREVIEW

Many page elements need a web address, called a URL:

  • An image needs a URL in its src.
  • A download link needs a URL in its href.
  • A video player needs a URL for its source.

A Blob is not a URL. So the browser lets you ask for a short, temporary one with URL.createObjectURL(blob). This is called an object URL. It starts with blob:, and it only works inside this page.

Real-life analogyAn object URL is a download link

A download link on a website is short. It doesn't contain the file; it only says where the file is. When you click it, you get the file. When the site takes the link down, it stops working.

In real life: A file on a website
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: Clicking the link
In JavaScript: An element loading its src or href
In real life: Taking the link down
In JavaScript: URL.revokeObjectURL(url)
Make and cancel 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);

Line 1 makes a Blob with the text download me. Line 2 asks for an object URL that points at it. Line 3 gives that URL to the link. Line 4 sets the download attribute, which suggests a file name, note.txt. Line 7 cancels the URL when it is no longer needed.

A page with a download link called note.txt. Its href is the url, a tag that says blob. The tag points at a Blob that holds the text download me.pagedownload linknote.txtlink.href = urlURL.createObjectURL(blob)blob:…url"download me"blob
URL.createObjectURL(blob) makes a short blob: address that points at the Blob. The link uses that address, so clicking it downloads note.txt.
Download a CSV file made in the pagePop out in the code editor (opens in a new tab)JavaScript
const rows = [["Name", "Score"], ["Asha", 9]];
const csv = rows.map((row) => row.join(",")).join("\n");
const blob = new Blob([csv], { type: "text/csv" });
const url = URL.createObjectURL(blob);
link.href = url;
link.download = "scores.csv";
console.log(csv);

A CSV file is a table written as text: one row per line, with commas between the cells. Line 1 has two rows. Line 2 joins each row with commas, then joins the rows with a line break. Line 3 puts that text in a Blob. Lines 4 to 6 make an object URL and give it to the link, with the file name scores.csv. Line 7 prints the CSV text.

Keep an object URL only while the page needs it. Cancel it with URL.revokeObjectURL(url) when:

  • a new preview replaces the old one,
  • a Reset button clears the preview,
  • the part of the page that showed it is removed.

Cancelling tells the browser it may free the memory the bytes use. Don't cancel too early: wait until the image has loaded or the link has been clicked.

A data URL is a different thing. It puts the whole file inside the URL, written as base64 text. Base64 writes bytes using only letters, digits, and a few symbols, so it is about one third bigger than the bytes. FileReader's readAsDataURL() makes data URLs. For previews and downloads, object URLs are usually the better choice.

FileReader: the older way to read

STEP THROUGH

The Blob methods return promises. await blob.text() gives you all the text. await blob.arrayBuffer() gives you all the bytes.

FileReader is older, and it works with events instead. An event is a message the browser sends when something happens. You use it in three steps:

  1. Make a reader with new FileReader().
  2. Add listeners, functions that run when each event arrives.
  3. Start the read with a method such as readAsText(), readAsArrayBuffer(), or readAsDataURL().
Real-life analogyFileReader is a parcel tracker

A parcel tracker sends you a message at each stage: the parcel left, it is on the way, it arrived. At the end, the tracking closes. FileReader sends an event at each stage of a read in the same way.

In real life: Tracking starts
In JavaScript: loadstart
In real life: The progress bar moves
In JavaScript: progress
In real life: The parcel arrives
In JavaScript: load
In real life: Tracking closes, whatever happened
In JavaScript: loadend
Step through: the order of FileReader events
Step 0 of 13Ready
Your turn: follow the blue line

Pick a path, guess the order of the events, then step through the code.

Running in
  1. script
Next: line 1
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(" -> "));
CallStoreChangeResultBlue line: runs next. Ran: already executed.
Recent returnsNothing yet. Start with the blue line.
Pick how the read ends

This is a small pretend reader that sends the events in the same order. A real browser may send more than one progress event, depending on the 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.

The step-through uses a small pretend reader, makeReader, that fires the events in the same order as a real FileReader. A real reader fires them a little later, not all at once.

The order depends on how the read ends:

  • Success: loadstart, then one or more progress events, then load, then loadend.
  • Stopped early: loadstart, then abort, then loadend.
  • Failed: loadstart, then error, then loadend.
Success: loadstart, then progress, then load, then loadend. Abort: loadstart, then abort, then loadend. Both paths end with loadend.successloadstartprogressloadloadendabortloadstartabortloadend
A successful read fires loadstart, progress, load, then loadend. An aborted read fires abort instead, but it still ends with loadend.

To read a whole file, the promise methods are simpler. To show a progress bar or let the user stop a read, use FileReader.

Progress demo: watch a read happen
Read with progress eventsPop 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 made-up Blob. None of your files are used.
Try it yourself

FileReader sends progress events while it reads. The browser decides how big each piece is, so you may see one event or several. The Blob is made in this page, with about 4 million bytes.

A simple model splits 4096 bytes into four pieces: 25%, 50%, 75%, 100%. A real browser may send different numbers.

Look at files from a picker or a drop

INTERACTIVE

A page can get File objects in two ways:

  • a file input, <input type="file">, which opens a file picker,
  • a drop zone, an area of the page where you can drop files.

Once the user gives the page a file, the page can read its facts, read its bytes, or send it to a server later. Picking or dropping a file does not upload it.

Read the picked FilePop out in the code editor (opens in a new tab)JavaScript
const input = document.querySelector("input[type=file]");
input.addEventListener("change", () => {
  const [file] = input.files;
  console.log(file ? file.name : "no file selected");
});

Line 1 finds the file input. Line 2 runs a function each time the user picks a file. Line 3 takes the first file from input.files. Line 4 prints its name, or no file selected if there is none.

input.files is a FileList, a list of File objects. The first file is at index 0. If the user cancels, the list is empty. The input's accept attribute tells the picker which files to show, but it is only a hint. Check the File yourself.

File inspector: facts and previews
A drop zone that shows a previewPop 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);  }});
Your filenone yet
Drop a file here

No file picked yet.

Try it yourself

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

The page gets a File only after you pick or drop it. This demo never sends it anywhere.

The inspector's code listens for two events on the drop zone:

  • dragover fires while a file is dragged over the zone. Calling event.preventDefault() here tells the browser this zone accepts drops.
  • drop fires when the file is let go. event.dataTransfer.files holds the dropped files.

Dropping a folder may not give an ordinary File, so the list can be empty. A good drop zone checks for that and doesn't crash.

Show a preview of a picked imagePop out in the code editor (opens in a new tab)JavaScript
const file = input.files[0];
if (file?.type.startsWith("image/")) {
  preview.src = URL.createObjectURL(file);
  console.log("image preview ready");
}

Line 2 checks that a file was picked and that its type starts with image/. The ?. stops the check safely if there is no file. Line 3 gives the image an object URL, so it shows the picture. Line 4 prints image preview ready.

Check size and type before uploadPop out in the code editor (opens in a new tab)JavaScript
const maxBytes = 1_000_000;
const file = input.files[0];
const allowed = file?.type === "image/png" && file.size <= maxBytes;
console.log(allowed ? "ready to upload" : "reject before upload");

Line 1 sets the largest size allowed: one million bytes. Line 3 allows the file only if it is a PNG image and not too big. Line 4 prints ready to upload or reject before upload. This check gives the user quick feedback. The server must still check the file again.

To send files to a server, use them with FormData. To keep files in the browser for later, compare the tools in Cache API and file storage.

Pick the right way to read

SORT

Each file job needs something different. Ask what you need:

  • all the text,
  • the exact bytes,
  • the bytes a piece at a time,
  • a URL to show or download the file,
  • a URL that holds the whole file as text, or
  • progress events.

Then pick the tool that does that job.

Read each row of the table as a job, the tool to use, and the reason.

Which tool fits each file job
What you want to doTool to useWhy it fits
Read a text fileawait file.text()It gives you all the text in one short line of code.
Work with the exact bytesawait file.arrayBuffer()It gives you every byte, for files that aren't text.
Show a picture before uploadURL.createObjectURL(file)The image loads from a short temporary URL, with no base64 copy.
Show progress or let the user stopFileReaderIt sends progress, abort, error, and loadend events.
Handle a huge file a piece at a timeblob.stream()A stream gives you the bytes in chunks, one after another.
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

Put each tool under the job it does best.

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

A stream gives you the bytes in pieces, called chunks, one after another. That way the page doesn't need to hold a huge file in memory all at once.

Read a Blob a piece at a timePop out in the code editor (opens in a new tab)JavaScript
const reader = blob.stream().getReader();
let chunks = 0;
for (;;) {
  const { done, value } = await reader.read();
  if (done) break;
  chunks += 1;
  console.log(value.byteLength);
}
console.log(chunks);

Line 1 opens the Blob as a stream and gets a reader for it. Line 2 starts a chunk count at 0. The loop on line 3 runs until line 5 stops it. Line 4 waits for the next chunk. When there are no more chunks, done is true and line 5 leaves the loop. Otherwise, line 6 counts the chunk and line 7 prints its size in bytes. Line 9 prints how many chunks there were.

The Streams and progress lesson explains streams in more detail. For this lesson, remember the five choices: all the text, all the bytes, chunks, a preview URL, or events.

Where you will use this

PRACTICAL

You use Files and Blobs whenever a page works with files without loading a new page. Some common jobs:

  • Save data as a file: turn rows into CSV text, put it in a Blob, make an object URL, and give it to an <a download> link.
  • Preview before upload: take a File from an input. Show a picture with an object URL, or show text with file.text().
  • Pictures made in the page: a canvas, the drawing area of a page, can give you its picture as a Blob. You can then preview it or let the user download it.
  • Working offline: keep files in the browser's own storage, such as IndexedDB or the Origin Private File System, so the page can use them without the internet.
Privacy rule

The browser never gives your page a full path like /Users/ada/taxes/receipt.pdf. It gives the file name and the bytes, and only after the user picks or drops the file. Browsers work this way on purpose, to keep the user's folders private.

Common mistakes

WATCH OUT
  • "Blob size is the string length." No. Blob size counts bytes. Letters with accents and emoji take more than one byte each.
  • "The type proves what kind of file it is." No. type is only a label. It can be empty or wrong.
  • "Picking a file uploads it." No. The file is sent only if your code sends it, for example with FormData and fetch.
  • "Object URLs go away by themselves right away." No. An object URL lasts until you cancel it or the page closes. Cancel previews you no longer need.
  • "FileReader is the only way to read a file." No. The Blob methods, like text(), are usually simpler. Use FileReader when you need its events.
  • "The browser shows the file's full path." No. It shows the file name only, not the folders it is in.

Practice exercises

5 EXERCISES
Exercise 1 · Warm-upLetters or bytes?

Predict the two lines this code prints.

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-upShow that a File is a Blob

    Run the code in a browser console or in Node 22, and write down the three lines it prints.

    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 last FileReader event

      Some clean-up code must run after every read, however it ends. Which FileReader event should it listen for?

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

        Exercise 4 · PracticeFix the preview that keeps using memory

        A page makes a new image preview each time the user picks a file. Which method should it call on the old preview's URL?

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

          Exercise 5 · ChallengePlan a safe file inspector

          Your page wants to show which folder a dropped file came from. Can JavaScript in the browser 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 count?

              Choose an answer to see the explanation.

            2. Question 2 of 8What does this code 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 code 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 cancel an object URL with URL.revokeObjectURL?

              Choose an answer to see the explanation.

            6. Question 6 of 8In what order does FileReader send events when a read works?

              Choose an answer to see the explanation.

            7. Question 7 of 8What is the best way to read all the text in a text file?

              Choose an answer to see the explanation.

            8. Question 8 of 8What must a drop zone do in its dragover listener so it can get a drop?

              Choose an answer to see the explanation.

            Key takeaways

            • A Blob holds bytes and a type label. A File is a Blob with a name and a last-changed time.
            • Blob size counts bytes, not letters. Letters with accents and emoji show the difference.
            • Read with text(), arrayBuffer(), and stream(). Use FileReader when you need progress, stopping, or data URLs.
            • Object URLs are short, temporary addresses for previews and downloads. Cancel them when you no longer need them.
            • File inputs and drop zones never show full paths, and they never upload files by themselves.

            Final definition.
            Blob and File are browser objects that hold bytes. They let JavaScript read, preview, and download files that the user picked or that the page made.

            Up next: Device & platform APIs.

            CompleteFrontend Clear concepts. Working examples.