Blob Construction



Blob is an established acronym formed from the Binary Large OBject notion. Blobs were first introduced as part of Google Gears programming interfaces. Now all A-grade browsers implement Blob API as well as its File subinterface. One of the latest trends in Blob API implementations is the availability of Blob constructor methods. BlobBuilder interfaces have been relegated, so the preferred way to build a Blob is to invoke its constructor and pass an argument list to it. Default no-argument constructor instantiates a binary object with its size equal to zero and with type property set to the empty string:

var blob=new Blob();
console.log(blob.size); // returns 0
console.log(blob.type); // returns empty string

An argument list required to create a Blob instance consists of two elements. The first argument is a sequence of ArrayBuffer, ArrayBufferView, Blob or DOMString objects. The second argument is optional: this is a BlobPropertyBag dictionary containing the Blob's MIME type and a value for line endings representation.

ArrayBuffer Objects

An ArrayBuffer is just an opaque container of data - a linear sequence of bytes. ArrayBuffer objects can be instantiated by the allocation of a fixed amount of bytes in the memory:

var arrayBuffer=new ArrayBuffer(8);

In the example above a new ArrayBuffer has been created, its byteLength property is equal to 8, all bytes are initialized to 0. ArrayBuffer objects are passed to Blob constructor methods as elements of the blobParts array:

var array=new Array(); // empty array

var arrayBuffer0=new ArrayBuffer(8); // ArrayBuffer containing 8 bytes is created
var arrayBuffer1=new ArrayBuffer(24); // the buffer capacity is 24 bytes
var arrayBuffer2=new ArrayBuffer(512); // the buffer capacity is 512 bytes

// filling array with values
array.push(arrayBuffer0); array.push(arrayBuffer1); array.push(arrayBuffer2);
// argument for Blob constructor is ready

var blob=new Blob(array); // Blob is created

The resulting Blob object's size is 544: this is the sum of byte length values of ArrayBuffer objects passed to the Blob constructor:

console.log(blob.size); // returns 544 - the size of the Blob in bytes
console.log(arrayBuffer0.byteLength+arrayBuffer1.byteLength+arrayBuffer2.byteLength); // 544

ArrayBuffer values in Blob constructors are allowed but considered deprecated. It is recommended that an instance of ArrayBufferView should be used instead.

ArrayBufferView Objects

ArrayBuffer API does not provide methods to move data out of or into a buffer. Neither does it make buffer bytes visible to the outer code. To represent an ArrayBuffer as a sequence of homogeneous binary data, a view of the given buffer is instantiated. The typed array view is backed by the buffer, but is not indexed on the bytes basis: the view's indices are type-specific.

var array=new Array();
var arrayBuffer=new ArrayBuffer(8); // 8 bytes buffer
var arrayBufferView0=new Uint8Array(arrayBuffer); // the length of this typed array is 8
var arrayBufferView1=new Uint16Array(arrayBuffer); // the length of this typed array is 4
var arrayBufferView2=new Uint32Array(arrayBuffer); // the length of this typed array is 2
array.push(arrayBufferView0); array.push(arrayBufferView1); array.push(arrayBufferView2);
var blob=new Blob(array); // the Blob's size is 24

8-byte ArrayBuffer backing three buffer views
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
________
________________
_________________________________

Uint8Array element: 8 bits; Uint8Array length: 8
Uint16Array element: 16 bits; Uint16Array length: 4
Uint32Array element: 32 bits; Uint32Array length: 2

The byteLength property of all typed arrays are the same (8 bytes), but length values differ. However, the resulting Blob's size is defined as a sum of ArrayBufferViews bytes length (8+8+8).

ArrayBufferViews provide access to the contents of their backing buffers, expose get/set methods and facilitate bulk transfer operations with bytes. Changes to the view alter the buffer, so modification to one view is immediately visible in other views with the same backing ArrayBuffer:

var array=new Array();
var arrayBuffer=new ArrayBuffer(8);
var arrayBufferView0=new Int8Array(arrayBuffer); // [0, 0, 0, 0, 0, 0, 0, 0]
window.crypto.getRandomValues(arrayBufferView0);
console.log(arrayBufferView0); // [-43, -13, -81, 124, -63, 21, -102, 78]
var arrayBufferView1=new Int16Array(arrayBuffer);
console.log(arrayBufferView1); // [-3115, 31919, 5569, 20122]
var arrayBufferView2=new Int32Array(arrayBuffer);
console.log(arrayBufferView2); // [2091906005, 1318720961]
array.push(arrayBufferView0); array.push(arrayBufferView1); array.push(arrayBufferView2);
var blob=new Blob(array);
console.log(blob.size); // 24 bytes

Blob Constructor: Files Array

Blob constructors accept arrays of other Blobs as their arguments. Files are Blobs, too, so a File instance can be used to build a Blob:

<input type="file" accept="image/png" onchange="blobDemo(this.files);">

// handling change event
function blobDemo(fileList) {
 var array=new Array();
 var file=fileList[0];
 array.push(file);
 var blob=new Blob(array, {type:"image/png"});
 var url=window.URL.createObjectURL(blob);
 var image=new Image();
 image.src=url;
 image.onload=function(loadEvent) {
  window.URL.revokeObjectURL(blob);
 };
 document.body.appendChild(image);
}

The code introduces a example of using the BlobPropertyBag dictionary - an optional argument frequently employed in Blob construction methods. The dictionary in the code snippet above indicates the media type of the created Blob (image/png). The type must be a valid MIME type.

Blob Constructor: Strings Array

Blobs can be used for working not only with binary data but also with strings:

var array=new Array("element0", "element1", "element2"); // array of three string elements
var blob=new Blob(array); // Blob's size is 24: 8 bytes are used to encode each element

The indication of the media type enhances string data manipulations:

var array=new Array("<p>element0</p>", "<p>element1</p>", "<p>element2</p>");
var blobPropertyBag={type: "text/html; charset="+document.charset};
var blob=new Blob(array, blobPropertyBag);
var fileReader=new FileReader();
fileReader.onload=function(event) {
 document.getElementById("container").innerHTML=event.target.result;
};
fileReader.readAsText(blob);

In addition to MIME types, BlobPropertyBag instances can have information related to proper handling of string endings. If the endings member of the dictionary is equal to transparent (this is a value by default), code points in the string arguments remain unchanged:

var array=new Array("element0\n", "element1\n", "element2\n");
var blobPropertyBag={type: "text/plain", endings: "transparent"};
var blob=new Blob(array, blobPropertyBag);
console.log(blob.size); // blob.size returns 27
var fileReader=new FileReader();
fileReader.onload=function(event) {
 var text=event.target.result;
 console.log(text.length); // 27 characters
};
fileReader.readAsText(blob);

If the endings value is native, new line characters are transformed to the system-dependent line separator. For example, newlines in Windows are converted into \r\n pairs:

var array=new Array("element0\n", "element1\n", "element2\n");
var blobPropertyBag={type: "text/plain", endings: "native"};
var blob=new Blob(array, blobPropertyBag);
console.log(blob.size); // blob.size returns 30
var fileReader=new FileReader();
fileReader.onload=function(event) {
 var text=event.target.result;
 console.log(text.length); // 30 characters
};
fileReader.readAsText(blob);

Blob Constructor: Combination of Arguments

Blob constructor arguments can have various data types:

var arrayBuffer=new ArrayBuffer(8);
var arrayBufferView=new Int8Array(arrayBuffer);
var blobArg=new Blob(["data item 0", "data item 1"]);
var blob=new Blob([arrayBufferView, blobArg, "string data"]);
console.log(blob.size); // blob.size returns 41

Summary: Blob Construction

Blob Constructor