Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Round-tripping Blob to Array adds 48 to array values

I have two functions for converting between Blobs and arrays of bytes:

function arrayToBlob(data) {
    return new Blob(data);
}

function blobToArray(data, callback) {
    let reader = new FileReader();
    reader.addEventListener("loadend", function() {
        callback(Array.from(new Uint8Array(reader.result)));
    });
    reader.readAsArrayBuffer(data);
}

(blobToArray takes a callback because it requires setting up an event listener.)

I expect these functions to be inverses of each other, but when I run

blobToArray(arrayToBlob([1,2,3]), console.log)

the result I get is not [1, 2, 3], but [49, 50, 51]. Presumably something I'm doing is causing the numbers to be converted to their ASCII values, but I don't know which part is responsible.

like image 712
Challenger5 Avatar asked Jul 08 '26 11:07

Challenger5


1 Answers

The problem is that Blob's constructor converts numbers in your array to strings. As per MDN documentation Blob's constructor takes and array of an Array or ArrayBuffer, ArrayBufferView, Blob, DOMString objects, or a mix of any of such objects, as a first parameter. All these will be concatenated and put into the Blob. So each element in the array that you passed is treated on it's own. They are converted to strings (see ASCII table, the code for '1' is 49 and so on) and put into the Blob.
Take note that the results of these 4 expressions are the same:

function arrayToBlob(data) {
    return new Blob(data);
}

function blobToArray(data, callback) {
    let reader = new FileReader();
    reader.addEventListener("loadend", function() {
        callback(Array.from(new Uint8Array(reader.result)));
    });
    reader.readAsArrayBuffer(data);
}

blobToArray(arrayToBlob([1,2,3]), console.log)
blobToArray(arrayToBlob(['1','2','3']), console.log)
blobToArray(arrayToBlob([123]), console.log)
blobToArray(arrayToBlob(['123']), console.log)

If you want to get a binary array back you need to pass a propper binary array to the Blob:

function arrayToBlob(data) {
    return new Blob([data]);
}

function blobToArray(data, callback) {
    let reader = new FileReader();
    reader.addEventListener("loadend", function() {
        callback(Array.from(new Uint8Array(reader.result)));
    });
    reader.readAsArrayBuffer(data);
}

var arr = new Uint8Array(3);
arr[0]=1;
arr[1]=2;
arr[2]=3;

blobToArray(arrayToBlob(arr), console.log)

Pay attansion how I pass the Uint8Array to the Blob : return new Blob([data]);. I put it inside an array so it's not get treated as array of objects itself that Blob takes as 1st parameter.
In conclusion: you did not really do a round trip, you started with one type of array and converted it to another type of array. If you use the propper array from the start then every thing works.

like image 75
Dmitry Avatar answered Jul 10 '26 16:07

Dmitry