I'm retrieving an ArrayBuffer over XHR and want to save it to the FileSystem API using a FileWriter. The FileWriter expects a Blob and the Blob constructor won't take an ArrayBuffer, it takes an ArrayBufferView.
There are many ArrayBufferViews to choose from, how do I know which is the correct to use?
At MDN, you can find an overview of all available ArrayBufferView
subclasses:
Type | Bytes | Description | Equivalent C type |
---|---|---|---|
Int8Array |
1 | 8-bit twos complement signed integer | int8_t |
Uint8Array |
1 | 8-bit unsigned integer | uint8_t |
Uint8ClampedArray |
1 | 8-bit unsigned integer (clamped) | uint8_t |
Int16Array |
2 | 16-bit twos complement signed integer | int16_t |
Uint16Array |
2 | 16-bit unsigned integer | uint16_t |
Int32Array |
4 | 32-bit twos complement signed integer | int32_t |
Uint32Array |
4 | 32-bit unsigned integer | uint32_t |
Float32Array |
4 | 32-bit IEEE floating point number | float |
Float64Array |
8 | 64-bit IEEE floating point number | double |
BigInt64Array |
8 | 64-bit two's complement signed integer | int64_t |
BigUint64Array |
8 | 64-bit unsigned integer | uint64_t |
Basically, this lists what memory spaces each item of the array would occupy and if it's a plain number or a FP number. I'm not sure what languages you're familiar with, but if it also covers Java, then it is basically the same choice as you'd make on byte[]
, short[]
, int[]
, float[]
and double[]
(Java is always signed, so that part doesn't matter).
We know, binary data like images is usually represented as a byte array. A short/int/long array can also, but this is a waste of memory space. If you would store a 100KB image (note that "B" stands for byte, which is 8 bits) in an int array instead of a byte array, then it would occupy 400KB of memory, which is a waste of 300KB. So the smallest one, Int8Array
, would already suffice with regard to memory space. If you'd ever like to programmatically traverse it — which is very unlikely in this case — as an unsigned array, then you may opt for the Uint8Array
instead where each item holds values 0
to 255
instead of values -128
to 127
.
Here's a copy'n'paste'n'runnable kickoff example which downloads an image file from the server, saves it to the temporary local storage space and presents it as an <img>
in the body (little jQuery is required for that part). This example assumes that the image.png
file is located in the same base folder as the JS (or HTML, in case JS is inlined) file is been downloaded from:
window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;
window.requestFileSystem(window.TEMPORARY, 1024*1024, startDownload, errorHandler);
var errorHandler = function(error) {
console.log('FS error: ' + error);
}
var xhr = new XMLHttpRequest();
xhr.open('GET', 'image.png', true);
xhr.responseType = 'arraybuffer';
function startDownload(fileSystem) {
xhr.onload = function(event) {
var content = new Int8Array(this.response);
fileSystem.root.getFile('/image.png', { 'create': true }, function(fileEntry) {
fileEntry.createWriter(function(fileWriter) {
fileWriter.onwriteend = function(event) {
$('body').append('<p>Image successfully downloaded:</p>')
.append('<p><img src="' + fileEntry.toURL() + '"/></p>');
};
var blob = new Blob([content], { type: 'image/png' });
fileWriter.write(blob);
}, errorHandler);
});
}
xhr.send();
}
Note, as of the current state, this works in Chrome, Edge and Opera only and not (yet?) in Safari nor Firefox.