How to go from Blob to ArrayBuffer

前端 未结 6 1020
旧时难觅i
旧时难觅i 2020-11-27 10:20

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(arrayBuf         


        
相关标签:
6条回答
  • 2020-11-27 10:38

    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:

    • https://developer.mozilla.org/en-US/docs/Web/API/FileReader#readAsArrayBuffer()
    • https://www.w3.org/TR/FileAPI/#dfn-readAsArrayBuffer
    0 讨论(0)
  • 2020-11-27 10:47

    There is now (Chrome 76+ & FF 69+) a Blob.prototype.arrayBuffer() method which will return a Promise resolving with an ArrayBuffer representing the Blob's data.

    (async () => {
      const blob = new Blob(['hello']);
      const buf = await blob.arrayBuffer();
      console.log( buf.byteLength ); // 5
    })();

    0 讨论(0)
  • 2020-11-27 10:53

    The Response API consumes a (immutable) Blob from which the data can be retrieved in several ways. The OP only asked for ArrayBuffer, and here's a demonstration of it.

    var blob = GetABlobSomehow();
    
    // NOTE: you will need to wrap this up in a async block first.
    /* Use the await keyword to wait for the Promise to resolve */
    await new Response(blob).arrayBuffer();   //=> <ArrayBuffer>
    

    alternatively you could use this:

    new Response(blob).arrayBuffer()
    .then(/* <function> */);
    

    Note: This API isn't compatible with older (ancient) browsers so take a look to the Browser Compatibility Table to be on the safe side ;)

    0 讨论(0)
  • 2020-11-27 10:56

    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.

    0 讨论(0)
  • 2020-11-27 11:01

    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);
    
    0 讨论(0)
  • 2020-11-27 11:03

    await blob.arrayBuffer() is good.

    The problem is when iOS / Safari support is needed.. for that  one would need this:

    Blob.prototype.arrayBuffer ??=function(){ return new Response(this).arrayBuffer() }
    
    0 讨论(0)
提交回复
热议问题