Web APIsJavaScriptMedium

What is a Blob and how does it differ from a File?

01

The Short Answer

A Blob (Binary Large Object) is an immutable chunk of raw binary data. It represents file-like data that doesn't necessarily come from the file system — it could be text you generated, an image you fetched, or bytes you constructed in memory. A File is just a Blob with a name and a last-modified timestamp bolted on.

02

What a Blob Looks Like

A Blob has only two properties — size (in bytes) and type (MIME type). It's intentionally simple. You can't modify a Blob once it's created — you can only read it or slice it into smaller Blobs.

creating-blobs.tstypescript
// Create a Blob from a string
const textBlob = new Blob(['Hello, World!'], { type: 'text/plain' });
console.log(textBlob.size); // 13
console.log(textBlob.type); // "text/plain"

// Create a Blob from JSON
const data = { name: 'Alice', age: 30 };
const jsonBlob = new Blob([JSON.stringify(data)], { type: 'application/json' });

// Create a Blob from multiple parts (they get concatenated)
const multiBlob = new Blob(
  ['Part 1, ', 'Part 2, ', new Uint8Array([80, 97, 114, 116, 32, 51])],
  { type: 'text/plain' }
);
// Result: "Part 1, Part 2, Part 3"

// Create a Blob from another Blob + extra data
const combined = new Blob([textBlob, '\nMore text'], { type: 'text/plain' });

The constructor takes an array

The first argument to new Blob() is always an array of parts. Each part can be a string, an ArrayBuffer, a TypedArray, or another Blob. They get concatenated in order into one binary chunk.

03

Blob vs File

File extends Blob. It adds name and lastModified — that's it. Every File IS a Blob, but not every Blob is a File.

blob-vs-file.tstypescript
// A Blob — raw data, no filename
const blob = new Blob(['csv,data,here'], { type: 'text/csv' });
console.log(blob.name);         // undefined
console.log(blob.lastModified); // undefined

// A File — a Blob with metadata
const file = new File(['csv,data,here'], 'export.csv', {
  type: 'text/csv',
  lastModified: Date.now()
});
console.log(file.name);         // "export.csv"
console.log(file.lastModified); // 1717500000000
console.log(file.size);         // 13 (inherited from Blob)
console.log(file instanceof Blob); // true ✓

// When a user picks a file via <input type="file">, you get a File object
const input = document.querySelector('input[type=file]') as HTMLInputElement;
input.addEventListener('change', () => {
  const userFile = input.files![0]; // This is a File (which is a Blob)
  console.log(userFile.name);       // "photo.jpg"
  console.log(userFile.size);       // 2048000
  console.log(userFile.type);       // "image/jpeg"
});

When to use which

  • Use `Blob` when you're generating data in code (CSV export, JSON download, canvas image)
  • Use `File` when you need a filename (uploading to a server, drag-and-drop interfaces)
  • You receive `File` objects from `<input type="file">` and the Drag and Drop API
04

Reading a Blob's Contents

Blobs are opaque — you can't peek inside without explicitly reading them. There are two approaches: the modern async methods on Blob itself, and the older FileReader API.

reading-blobs.tstypescript
const blob = new Blob(['Hello, Blob!'], { type: 'text/plain' });

// ✅ Modern approach (returns Promises — clean and simple)
const text = await blob.text();            // "Hello, Blob!"
const buffer = await blob.arrayBuffer();   // ArrayBuffer of raw bytes
const stream = blob.stream();              // ReadableStream for chunked reading

// 🕰️ Legacy approach (event-based — more verbose)
const reader = new FileReader();
reader.onload = () => console.log(reader.result); // "Hello, Blob!"
reader.readAsText(blob);

// FileReader also supports:
// reader.readAsArrayBuffer(blob)  → ArrayBuffer
// reader.readAsDataURL(blob)      → "data:text/plain;base64,SGVsbG8s..."

Prefer the modern methods

Use blob.text(), blob.arrayBuffer(), and blob.stream() in modern code. They return Promises, work with async/await, and are much cleaner than FileReader's callback-based API. Only fall back to FileReader if you need readAsDataURL() or must support very old browsers.

05

Slicing a Blob

blob.slice() creates a new Blob that references a portion of the original data — without copying it in memory. This is key for chunked uploads and large file processing.

slicing.tstypescript
const bigBlob = new Blob(['ABCDEFGHIJ']); // 10 bytes

// slice(start, end) — just like Array.slice()
const chunk1 = bigBlob.slice(0, 5);   // "ABCDE"
const chunk2 = bigBlob.slice(5, 10);  // "FGHIJ"

// Negative indices work too
const lastThree = bigBlob.slice(-3);  // "HIJ"

// The original Blob is untouched — slicing creates a lightweight view
console.log(bigBlob.size);  // still 10
console.log(chunk1.size);   // 5
06

Practical Examples

download-csv.tstypescript
// Generate and download a CSV file entirely in the browser
function downloadCSV(rows: string[][]) {
  const csvContent = rows.map(row => row.join(',')).join('\n');
  const blob = new Blob([csvContent], { type: 'text/csv' });

  const url = URL.createObjectURL(blob);  // Create a temporary URL
  const a = document.createElement('a');
  a.href = url;
  a.download = 'export.csv';
  a.click();

  URL.revokeObjectURL(url);  // Free memory
}

downloadCSV([['Name', 'Age'], ['Alice', '30'], ['Bob', '25']]);
image-preview.tstypescript
// Preview an image before uploading it
const input = document.querySelector('input[type=file]') as HTMLInputElement;
const preview = document.querySelector('img') as HTMLImageElement;

input.addEventListener('change', () => {
  const file = input.files![0]; // File is a Blob
  if (!file.type.startsWith('image/')) return;

  // Create a URL pointing to the Blob in memory
  const objectURL = URL.createObjectURL(file);
  preview.src = objectURL;

  // Clean up when the image loads
  preview.onload = () => URL.revokeObjectURL(objectURL);
});
canvas-to-blob.tstypescript
// Convert a canvas drawing to a Blob and upload it
const canvas = document.querySelector('canvas') as HTMLCanvasElement;

canvas.toBlob(async (blob) => {
  if (!blob) return;

  const formData = new FormData();
  formData.append('avatar', blob, 'avatar.png');

  await fetch('/api/upload-avatar', {
    method: 'POST',
    body: formData
  });
}, 'image/png');
07

Common Mistakes

🧠

Forgetting to revoke object URLs

Every `URL.createObjectURL()` keeps the Blob in memory until the page unloads or you explicitly revoke it. Creating many without revoking leaks memory.

Always call `URL.revokeObjectURL(url)` when you're done — after download completes or image loads.

🔒

Treating Blobs as mutable

Blobs are immutable. You can't modify their contents after creation. Trying to "edit" a Blob means creating a new one.

Read the Blob, modify the data, then create a new Blob from the modified data.

08

Why Interviewers Ask This

File handling is everywhere — uploads, downloads, image previews, PDF generation, clipboard operations. Understanding Blobs shows you can work with binary data in the browser, manage memory correctly, and build features like file exports without needing a server round-trip.

Quick Revision Cheat Sheet

Blob: Immutable binary data with `size` and `type` properties

File: A Blob subclass that adds `name` and `lastModified`

Reading: `blob.text()`, `blob.arrayBuffer()`, `blob.stream()`

Slicing: `blob.slice(start, end)` — lightweight, no copy

Object URL: `URL.createObjectURL(blob)` → temporary URL to the Blob in memory

Cleanup: Always `URL.revokeObjectURL()` when done to free memory