repost: What is a Blob object in JavaScript?

A Blob object is a versatile container for files and data.

Though it stands for Binary Large Object, it is also used to contain small amounts of data.

By placing files or file-like objects in a Blob, various methods become available that can be useful for accessing, encoding and transferring the data.

# Why use a Blob?

In itself, a Blob isn’t particularly interesting or useful.

The main reason storing data inside a Blob is useful is because of the methods available on it that make it useful for making the data accessible and passing it around.

Here are some common examples:

  • Create a data URL to the data using the FileReader API
  • Create an object URL to the data in memory using URL.createObjectURL()
  • Create readable stream ( readableStream ) using the Streams API
  • Enable use of the slice method to get a subset of the data

We’ll take a look at some examples soon. But first…

# How to create a Blob

You can create a new Blob by calling the Blob constructor object.

To use it to create a new Blob object, use the new operator before calling Blob and pass the data into the parentheses inside an array (even if there is only one item!).

As a second argument, you should specify a MIME type (e.g. ‘text/plain’, ‘application/json’) as the type property inside an object . This is technically optional but if you do not specify a type, a receiving server may not know how to read the contents of the Blob.

1
2
3
4
5
6
const text = "I'm a little bit of data";

const blob = new Blob([text], { type: "text/plain" });

console.log(blob);
// Blob {size: 24, type: 'text/plain'}

As you can see, a Blob object has two properties: size (in bytes) and type (MIME type).

Apart from this, a Blob object is opaque about its contents.

# Download data to Blob format

You can use the Fetch function to download data so that it is stored in a Blob object.

Just call the blob() method on the response object:

1
2
3
fetch("https://picsum.photos/400/400")
.then((res) => res.blob())
.then((res) => console.log(res)); // e.g. Blob {size: 54892, type: 'image/jpeg'}

# Useful things you can do with a Blob

# #1: Create a data URL

Using the FileReader API, you can create a data URL to a Blob object. A data URL is a string-encoded reference to the contents of the Blob that functions like a regular URL.

For example, in the following snippet, a data URL is created for the JSON string:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const user = {
name: "User",
occupation: "A User",
address: "1 User Road",
};

const json = JSON.stringify(user);

const fr = new FileReader();
// Creates new FileReader instance

fr.readAsDataURL(new Blob([json], { type: "application/json" }));
// Places JSON string in Blob and read contents as data URL

fr.addEventListener("load", () => {
// Waits for file reading to complete...

console.log(fr.result);
// data:application/json;base64,eyJuYW1lIjoiVXNlciIsIm9jY3VwYXRpb24iOiJBIFVzZXIiLCJhZGRyZXNzIjoiMSBVc2VyIFJvYWQifQ==
});

Just like a regular URL to a JSON file, if you enter it in your browser, you will see the JSON object.

The difference to a regular URL is that it does not link to an external resource. The data is contained in the URL!

A data URL is of type string but doesn’t have to contain string data.

For example, you can create a data URL to an image:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<input type="file" accept="image/png">

<script>

const input = document.querySelector('input');

input.addEventListener('change', () => {
// Fires when users select a file

const fr = new FileReader();

fr.readAsDataURL(input.files[0]);
// A single file will always be located at 0 on the files array

fr.addEventListener('load', () => {

console.log(fr.result);
// data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABRIAAATQCAYAAACP9rm5AAAAAXNSR0I...

})

});
</script>

In the above example, the Blob constructor was not called because a File object is also a Blob.

A useful feature of stringifying data in this way is that it can then be stored in localStorage or sent to a URL (another page or server) as a URL parameter.

# #2: Create an object URL

An object URL also functions like a regular URL, pointing to the contents of a Blob object.

You can create one by calling the globally available URL.createObjectURL() method, passing in as an argument a Blob object:

1
2
3
4
5
6
7
8
9
fetch("https://picsum.photos/500/500")
.then((res) => res.blob())
.then((res) => generateURL(res));

function generateURL(blob) {
const url = URL.createObjectURL(blob);

console.log(url); // e.g. blob:null/ac27e970-43f0-41d1-a662-9268c0849f40
}

Unlike a data URL, an object URL does not contain the file data. Instead, it points to the file contents stored in browser memory.

Therefore, anything that clears browser memory will make an object URL invalid (e.g. does not survive a page refresh!).

One example of where you may want to use an object URL instead of a data URI is to create a client-side file download, like below. By using an object URL, no conversion to string format is necessary:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const data = "Please download me!";
const myBlob = new Blob([data], { type: "text/plain" });
blobURL = URL.createObjectURL(myBlob);

const a = document.createElement("a");
a.setAttribute("href", blobURL);
a.setAttribute("download", "blob-test.txt");

a.style.display = "none";
document.body.appendChild(a);

a.click();

document.body.removeChild(a);
URL.revokeObjectURL(blobURL);

Because a file will always exist in memory as long as an object URL exists pointing to it, it is good practice to use revokeObjectURL() to clear it if it is no longer necessary.

# #3: Split a file into parts

Using the slice() method on a Blob, you can retrieve specified bytes from a Blob:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const obj = {
name: "Bateman",
job: "Mergers & Aquisitions",
};

const json = JSON.stringify(obj);

const blob = new Blob([json], { type: "application/json" });
console.log(blob); // Blob {size: 48, type: 'application/json'}

blobSlice(blob, 0, 10); // Blob {size: 10, type: ''}

function blobSlice(blob, start, end) {
return blob.slice(start, end);
}

# #4: Create a readable stream

For larger file objects, it can useful to create a readable stream for them. This enables methods to be used that make the file easier to read and write.

You can easily turn a Blob object into an object of type ReadableStream by calling stream() on the Blob itself:

1
2
3
4
5
const text = "Some text to Blobbify";

const blob = new Blob([text], { type: "plain/text" });

const readableStream = blob.stream(); // ReadableStream {locked: false}
Edited on