JavaScript Blob

The browser has additional high-level objects. Among them is the Blob. The Blob object visualizes a blob that is a file-like object of immutable. The Blob is a raw data: you can read it both as binary data or text. It consists of an optional string type, blobParts, strings, as well as BufferSource.

Constructing a Blob

For constructing a Blob from other data and non-blob objects, the Blob() constructor is used. Its syntax is the following:

new Blob(blobParts, options);

Now, let’s check out an example of creating Blob from a string:

// create Blob from string
let blob = new Blob(["<html>…</html>"], {
	type: 'text/html'
});
// important: the first argument must be an array [...]

In the next example, it is created from a typed array and strings:

// create Blob from a typed array and strings
let welcome = new Uint8Array([89, 101, 108, 99, 111, 109, 101]); // "Welcome" in binary form
let blob = new Blob([welcome, ' to ', 'W3Docs'], {type: 'text/plain'});

The Blob slices can be extracted with:

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

The arguments here are like array.slice. Negative numbers can also be used. Please, note that data can’t be changed directly in the Blob. Yet, it is possible to slice parts of the Blob, creating new Blob objects from them, mixing them into a new Blob, and so on.

Blob as URL

The Blob is flexible: you can, also, use it as URL for <img>, <a>, and other tags. The Blob objects can also be downloaded and uploaded with the help of type. It naturally transforms into Content-Type for network requests.

Let’s have a look at the following example:

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the Document</title>
  </head>
  <body>
    <!-- The download attribute causes the browser to download instead of navigating -->
    <a download="welcome.txt" href='#' id="link">Download</a>
    <script>
      let blob = new Blob(["Welcome to W3Docs"], {type: 'text/plain'});
      link.href = URL.createObjectURL(blob);
    </script>
  </body>
</html>

Also, in JavaScript, a link can be created dynamically, simulating a click by link.click(). After this action, the download will start automatically.

Here is another example without the usage of HTML:

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the Document</title>
  </head>
  <body>
    <script>
      let link = document.createElement('a');
      link.download = 'welcome.txt';
      let blob = new Blob(['Welcome to W3Docs'], {type: 'text/plain'});
      link.href = URL.createObjectURL(blob);
      link.click();
      URL.revokeObjectURL(link.href);      
    </script>
  </body>
</html>

A created URL can only be valid inside the current document. It allows referencing the Blob in <a>, <img>.

But, note that there can be a significant side-effect. Particularly, when there exists a mapping for a Blob, it can reside in the memory. The browser is not able to get rid of it.

On document onload, the mapping is automatically cleared, so, then, objects will be freed. But, in case of a long-living app, it won’t happen soon. So, in case of creating a URL, the Blob can hang in memory.

With URL.revokeObjectURL(url), you can remove the reference from the internal mapping, letting the Blob to be deleted, freeing the memory.

To Base 64

An alternative option to URL.createObjectURL is converting Blob into a base-64 encoded string.

Such encoding illustrates binary data as a string of an ultra-safe readable characters with ASCII-codes from 0 to 64. Fortunately, such encoding can be used in “data-urls”.

A data-url form is data:[<mediatype>][;base64],<data>. They can be used anywhere with regular URLs.

The string will be decoded by the browser, and the image will be shown. For transforming a Blob into base-64, the built-in FileReader is used. It is capable of reading data from Blobs in multiple formats.

The demo of downloading a blob via base-64 will look like this:

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the Document</title>
  </head>
  <body>
    <script>
      let link = document.createElement('a');
      link.download = 'welcome.txt';
      let blob = new Blob(['Welcome to W3Docs'], {type: 'text/plain'});
      let reader = new FileReader();
      reader.readAsDataURL(blob); // converts ta blob to base64 and calls onload
      reader.onload = function() {
        link.href = reader.result; // data url
        link.click();
      };      
    </script>
  </body>
</html>

Both of the ways are handy, but URL.createObjectURL(blob) is much more straightforward.

Image to Blob

It is possible to generate Blob of an image part, a whole image, or take a page screenshot. It is, particularly, useful for uploading it somewhere. Image operations are carried out through the <canvas> element.

  1. As a first step, it’s necessary to draw an image on canvas with canvas.drawImage.
  2. Then, gon on with calling the canvas method, which generates a .toBlob(callback, format, quality) and runs callback with it when completed.

To ArrayBuffer

The Blob constructor helps to generate a blob from anything, including BufferSource.

When you want to implement low-level processing, the lowest-level ArrayBuffer can be used from FileReader, like this:

// getting arrayBuffer from blob
let fileReader = new FileReader();
fileReader.readAsArrayBuffer(blob);
fileReader.onload = function (event) {
	let arrayBuffer = fileReader.result;
};

Summary

As you know, ArrayBuffer, BufferSource, and Uint8Array are considered binary data. A Blob is a binary data with type. Therefore, Blob is quite convenient for downloading and uploading operations, common in the browser.

Web-request methods such as fetch, XMLHttpRequest, and more can natively operate with Blob.

Also, Blob can be converted to low-binary data types.




Do you find this helpful?

Related articles