How to go from Blob to ArrayBuffer
我在研究Blob,发现有ArrayBuffer时,可以轻松地将其转换为Blob,如下所示:
1 2 | var dataView = new DataView(arrayBuffer); var blob = new Blob([dataView], { type: mimeString }); |
我现在的问题是,是否可以从Blob转换为ArrayBuffer?
您可以使用
这是一个简短的示例:
1 2 3 4 5 6 | var arrayBuffer; var fileReader = new FileReader(); fileReader.onload = function(event) { arrayBuffer = event.target.result; }; fileReader.readAsArrayBuffer(blob); |
这是一个更长的例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | // 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 |
这已在Chrome 2769,Firefox 2060和Safari 611的控制台中进行了测试。
这也是您可以使用的现场演示:https://jsfiddle.net/potatosalad/FbaM6/
更新2018-06-23:感谢Klaus Klein提供的关于
参考:
- https://developer.mozilla.org/zh-CN/docs/Web/API/FileReader#readAsArrayBuffer()
- https://www.w3.org/TR/FileAPI/#dfn-readAsArrayBuffer
1 2 3 4 5 | 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> |
或者,您可以使用以下方法:
1 2 | 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 ;)
或者您可以使用fetch API
1 | fetch(URL.createObjectURL(myBlob)).then(res => res.arrayBuffer()) |
我不知道性能的差异是什么,它也会显示在DevTools的"网络"选项卡中。
只是为了补充@potatosalad先生的答案。
实际上,您不需要访问函数作用域即可在onload回调上获取结果,可以在event参数上自由执行以下操作:
1 2 3 4 5 6 | var arrayBuffer; var fileReader = new FileReader(); fileReader.onload = function(event) { arrayBuffer = event.target.result; }; fileReader.readAsArrayBuffer(blob); |
为什么这样更好?因为这样我们可以使用箭头功能而不会丢失上下文
1 2 3 4 5 | var fileReader = new FileReader(); fileReader.onload = (event) => { this.externalScopeVariable = event.target.result; }; fileReader.readAsArrayBuffer(blob); |
现在有(Chrome 76+和FF 69+)Blob.prototype.arrayBuffer()方法,该方法将返回一个Promise解析,并使用一个表示Blob数据的ArrayBuffer进行解析。
1 2 3 4 5 | (async () => { const blob = new Blob(['hello']); const buf = await blob.arrayBuffer(); console.log( buf.byteLength ); // 5 })(); |
问题是何时需要iOS / Safari支持。一个需要这个:
1 | Blob.prototype.arrayBuffer ??=function(){ return new Response(this).arrayBuffer() } |