Get started with BLOBs in JavaScript


Reading time: 30 minutes

A BLOB (Binary Large OBject) is a data type which can be used to store binary data. We can convert our files and images into binary data and store it using BLOB. They are immutable objects that represent raw data. File is a derivation of BLOB that represents data from the file system.

ArrayBuffer, Uint8Array and other BufferSource are just “binary data”; a Blob represents “binary data with type”. This makes Blobs convenient for upload/download operations. Methods that perform web-requests, such as XMLHttpRequest, fetch and so on, can work with Blob natively, as well as with other binary types.

A Blob object represents a file-like object of immutable, raw data. Blobs represent data that isn't necessarily in a JavaScript-native format. The File interface is based on Blob, inheriting blob functionality and expanding it to support files on the user's system.

In JavaScript, Blob consists of an optional string type (a MIME-type usually), plus blobParts – a sequence of other Blob objects, strings and BufferSources, in any order.

blobJSinfo
(Source: Blob - JavaScript.info)

What are BLOBs used for?

BLOBS are widely used on the web and following are some of the use cases:

  • BLOBS enable use to define all forms of data such as HTML code files, images, videos and others in the same binary format. This enables us to include all forms of data in a single file without referring to external files.

This is used extensively in OpenGenus Quark which you can use to save webpages locally in the browser or your file system as a single file.

Install Quark on Chrome and enjoy your time offline
  • BLOBS can be used to improve page loading speed. On the web, external files like images and videos are fetched after the initial HTML code is downloaded which significantly slows down the page. An optimization technique is to convert all external data as BLOBS and add it to the initial HTML code to minimize external calls.

How to define a BLOB in JavaScript? (Constructor)

new Blob(blobParts, options)

This returns a newly created Blob object whose content consists of the concatenation of the array of values given in parameter.

  • blobParts is an array of Blob/BufferSource/String values.
  • options is an optional parameter (object).

options:

type (String) : A valid MIME-type like 'text/plain or 'image/png'. Default value: "".
endings (String) : specifies how the strings containing the line ending character '\n are to be written out. "native" : change to match host OS convention (\r\n for Windows) and "transparent" : endings are stored in blob without change. Default value: "transparent".

For example :

var myBlobParts = ['<html><h2>This is heading</h2></html>']; // an array consisting of a single DOMString
var myBlob = new Blob(myBlobParts, {type : 'text/html', endings: "transparent"}); // the blob

console.log(myBlob.size + " bytes size");
// Output: 37 bytes size
console.log(myBlob.type + " is the type");
// Output: text/html is the type

Properties of BLOB object

As shown in the example above, we can access the Blob.size and Blob.type properties to get its details.

Blob.size returns a number value indicating the size of data contained in the Blob, in bytes.
Blob.type returns a string which indicates the MIME-type of the file. It returns an empty string if the type couldn't be determined.

How to use Blobs as URL ?

You can also use a Blob as an URL for 'a', 'img' or other tags to show its contents. You can also download or upload blobs like this example :

<a download="hello.html" href='#' id="link">Download</a> your file here.

<script>
var myBlobParts = ['<html><h2>This is heading</h2></html>'];
var myBlob = new Blob(myBlobParts, {type : 'text/html'});

link.href = URL.createObjectURL(myBlob);
</script>

By clicking on the link, you can download a dynamically-generated blob as a file named hello.html with the contents as provided.

You can also construct a blob containing the data for an image, use URL.createObjectURL() to generate a url, and pass that url to HTMLImageElement.src to display the image you created without talking to a server :

<img id="myImg">

<script>

var xhr = new XMLHttpRequest();
xhr.open("GET", "books.jpeg");
xhr.responseType = "blob";
xhr.onload = response;
xhr.send();

function response(e) {
   var URL = window.URL || window.webkitURL;
   var imageUrl = URL.createObjectURL(this.response);
   document.querySelector("#myImg").src = imageUrl;
}
</script>

What are the Functions to work with BLOBS?

Blob.slice()
This method is used to create a new Blob object containing the data in the specified range of bytes of the source Blob.

var newBlob = blob.slice([byteStart], [byteEnd], [contentType]);

byteStart : The byte from which to include in the new blob. Default value is 0.
byteEnd : The byte before which to include in the new blob. (Note: This byte is not included.) Default value is the size of the blob.
contentType : The type of the new blob, by default ''.

<a download="hello.txt" href='#' id="newLink">Download</a> new blob

<script>
var myBlobParts = ['<html><h2>This is heading</h2></html>'];
var myBlob = new Blob(myBlobParts, {type : 'text/html', endings: "transparent"});

console.log(myBlob.size + " bytes size");
// Output: 37 bytes size
console.log(myBlob.type + " is the type");
// Output: text/html is the type

myLink.href = URL.createObjectURL(myBlob);

var newBlob = myBlob.slice(1, 17, 'text/plain');
console.log('slice size is', newBlob.size);
// Output: slice size is 16
console.log('slice type is', newBlob.type);
// Output: slice type is text/plain

newLink.href = URL.createObjectURL(newBlob); 
// The contents of the file "hello.txt" downloaded with the link:
// html><h2>This is
// (16 characters, starting from index 1 to 16)

Blobs are immutable.
We can’t change data directly in a blob, but we can slice parts of blobs, create new blobs from them, mix them into a new blob and so on.
This behavior is similar to JavaScript strings: we can’t change a character in a string, but we can make a new corrected string.

How to convert Canvas to Blob?

You can convert a canvas to a blob file using the method HTMLCanvasElement.toBlob().

canvas.toBlob(callback, mimeType, qualityArgument);

Arguments :
callback The callback function with the resulting Blob object as the argument.
mimeType A DOMString indicating the image format. Default type is image/png.
qualityArgument A number between 0 & 1, indicating image quality (if requested type is image/jpeg or image/webp).

// Get the canvas element you want to convert into blob
var canvas = document.getElementById('canvas');
canvas.toBlob(function(blob) {
    // If we want to download the blob as a file
    link.href = URL.createObjectURL(blob);
}, 'image/png');

What are the Contents of a BLOB?

In order to view, how data is stored in a blob, we will use the readAsDataURL method of FileReader API in JavaScript. The result attribute contains the data as a data: URL representing the file's data as a base64 encoded string.

var myBlob = new Blob(['<html><h2>This is heading</h2></html>'], {type : 'text/html'});

var reader = new FileReader();

// This fires after the blob has been read
reader.addEventListener('loadend', (e) => {
  var text = e.target.result;
  console.log("Contents : "+ text);
});

// Start reading the contents of blob
reader.readAsDataURL(myBlob);

The output in the console :

Contents : data:text/html;base64,PGh0bWw+PGgyPlRoaXMgaXMgaGVhZGluZzwvaDI+PC9odG1sPg==

The text contained in our file is base64-encoded. We can try extracting the encoded part and decode it using the method atob() to check that it is the same.

  // Extracting it from the character at index=22 only in this case as we
  // already know the contents of our Blob
  var extractText = text.slice(22);
  console.log("Decoded "+ atob(extractText));
  // Output : Decoded <html><h2>This is heading</h2></html>

References :

  1. Blob - JavaScript.info
  2. Blob - Web APIs | MDN

Question on BLOB

Consider the following piece of code:

var myBlobParts = ['Example Text'];
var myBlob = new Blob(myBlobParts, {type : 'text/plain'});

console.log("size is " + myBlob.size);
// Output: size is 12 bytes

var newBlob = myBlob.slice(-4, 12, 'text/plain');

What will be the contents of the 'newBlob' or what will be the error message?

Text
IndexOutOfBounds
Example Text
No error message and the 'newBlob' will be empty.
For a negative value, it's treated as an offset from the end of the Blob towards the beginning. For example, -4 would be the 4th from last byte in the Blob, i.e. 'T'. In other words, the relative start for a negative value will be max( size + start, 0).