131

我正在研究 Blob,我注意到当您有一个 ArrayBuffer 时,您可以轻松地将其转换为 Blob,如下所示:

var dataView = new DataView(arrayBuffer);
var blob = new Blob([dataView], { type: mimeString });

我现在的问题是,是否可以从 Blob 转到 ArrayBuffer?

4

7 回答 7

147

您可以使用FileReader作为.BlobArrayBuffer

这是一个简短的示例:

var arrayBuffer;
var fileReader = new FileReader();
fileReader.onload = function(event) {
    arrayBuffer = event.target.result;
};
fileReader.readAsArrayBuffer(blob);

这是一个更长的例子:

// 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 27-69、Firefox 20-60 和 Safari 6-11 的控制台中进行了测试。

这里还有一个你可以玩的现场演示:https ://jsfiddle.net/potatosalad/FbaM6/

2018 年 6 月 23 日更新:感谢 Klaus Klein 关于event.target.resultvs的提示this.result

参考:

于 2013-04-12T21:19:09.937 回答
59

ResponseAPI 使用一个(不可变的),Blob可以通过多种方式从中检索数据。OP只要求,这ArrayBuffer是一个演示。

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>

或者你可以使用这个:

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

注意:API与旧(古老)浏览器不兼容,因此请查看浏览器兼容性表以确保安全;)

于 2019-03-17T06:45:03.053 回答
19

或者你可以使用 fetch API

fetch(URL.createObjectURL(myBlob)).then(res => res.arrayBuffer())

我不知道性能差异是什么,这也会显示在 DevTools 的网络选项卡上。

于 2018-08-09T03:00:21.637 回答
17

只是为了补充@potatosalad 先生的回答。

您实际上不需要访问函数范围来获取onload回调的结果,您可以自由地对event参数执行以下操作:

var arrayBuffer;
var fileReader = new FileReader();
fileReader.onload = function(event) {
    arrayBuffer = event.target.result;
};
fileReader.readAsArrayBuffer(blob);

为什么这样更好?因为那样我们可以使用箭头函数而不会丢失上下文

var fileReader = new FileReader();
fileReader.onload = (event) => {
    this.externalScopeVariable = event.target.result;
};
fileReader.readAsArrayBuffer(blob);
于 2017-10-02T13:03:23.513 回答
8

await blob.arrayBuffer()很好。

问题是何时需要 iOS / Safari 支持.. 因为那个人需要这个

Blob.prototype.arrayBuffer ??=function(){ return new Response(this).arrayBuffer() }
于 2020-08-24T20:28:43.517 回答
7

现在(Chrome 76+ 和 FF 69+)有一个Blob.prototype.arrayBuffer ()方法,它将返回一个 Promise 解析,其中 ArrayBuffer 表示 Blob 的数据。

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

于 2020-02-13T06:51:54.433 回答
3

这是一个异步方法,它首先检查方法的可用性arrayBuffer。此功能向后兼容且面向未来。

async function blobToArrayBuffer(blob) {
    if ('arrayBuffer' in blob) return await blob.arrayBuffer();
    
    return new Promise((resolve, reject) => {
        const reader = new FileReader();
        reader.onload = () => resolve(reader.result);
        reader.onerror = () => reject;
        reader.readAsArrayBuffer(blob);
    });
}
于 2021-02-12T07:32:49.373 回答