I was studying Blobs, and I noticed that when you have an ArrayBuffer, you can easily convert this to a Blob as follows:
var dataView = new DataView(arrayBuffer);
var blob = new Blob([dataView], { type: mimeString });
The question I have now is, is it possible to go from a Blob to an ArrayBuffer?
The new Response
API is capable of decoding data from a (immutable) Blob
. This is the Core API which the Fetch API uses.
var blob = GetABlobSomehow();
var arrayBuffer = null;
/* Use the await keyword to wait for the Promise to resolve */
arrayBuffer = await new Response(blob).arrayBuffer(); //: ArrayBuffer
alternatively you could use this:
new Response(blob).arrayBuffer()
.then(/* function to handle */);
Note: The ES6 standard is new and is not supported by older browsers. See the Browser Compatibility Table for more detailed information about support on browsers.
You can use FileReader
to read the Blob
as an ArrayBuffer
.
Here's a short example:
var arrayBuffer;
var fileReader = new FileReader();
fileReader.onload = function(event) {
arrayBuffer = event.target.result;
};
fileReader.readAsArrayBuffer(blob);
Here's a longer example:
// ArrayBuffer -> Blob
var uint8Array = new Uint8Array([1, 2, 3]);
var arrayBuffer = uint8Array.buffer;
var blob = new Blob([arrayBuffer]);
// Blob -> ArrayBuffer
var uint8ArrayNew = null;
var arrayBufferNew = null;
var fileReader = new FileReader();
fileReader.onload = function(event) {
arrayBufferNew = event.target.result;
uint8ArrayNew = new Uint8Array(arrayBufferNew);
// warn if read values are not the same as the original values
// arrayEqual from: http://stackoverflow.com/questions/3115982/how-to-check-javascript-array-equals
function arrayEqual(a, b) { return !(a<b || b<a); };
if (arrayBufferNew.byteLength !== arrayBuffer.byteLength) // should be 3
console.warn("ArrayBuffer byteLength does not match");
if (arrayEqual(uint8ArrayNew, uint8Array) !== true) // should be [1,2,3]
console.warn("Uint8Array does not match");
};
fileReader.readAsArrayBuffer(blob);
fileReader.result; // also accessible this way once the blob has been read
This was tested out in the console of Chrome 27—69, Firefox 20—60, and Safari 6—11.
Here's also a live demonstration which you can play with: https://jsfiddle.net/potatosalad/FbaM6/
Update 2018-06-23: Thanks to Klaus Klein for the tip about event.target.result
versus this.result
Reference:
Just to complement Mr @potatosalad answer.
You don't actually need to access the function scope to get the result on the onload callback, you can freely do the following on the event parameter:
var arrayBuffer;
var fileReader = new FileReader();
fileReader.onload = function(event) {
arrayBuffer = event.target.result;
};
fileReader.readAsArrayBuffer(blob);
Why this is better? Because then we may use arrow function without losing the context
var fileReader = new FileReader();
fileReader.onload = (event) => {
this.externalScopeVariable = event.target.result;
};
fileReader.readAsArrayBuffer(blob);
Or you can use the fetch API
fetch(URL.createObjectURL(myBlob)).then(res => res.arrayBuffer())
I don't know what the performance difference is, and this will show up on your network tab in DevTools as well.
来源:https://stackoverflow.com/questions/15341912/how-to-go-from-blob-to-arraybuffer