如何从 Blob 到 ArrayBuffer

IT技术 javascript blob arraybuffer
2021-01-28 14:32:26

我正在研究 Blob,我注意到当你有一个 ArrayBuffer 时,你可以很容易地将它转换为一个 Blob,如下所示:

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

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

6个回答

您可以使用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-06-23 更新:感谢 Klaus Klein 提供关于event.target.resultvs的提示this.result

参考:

这看起来是不是有很多代码......对于一些应该很简单的事情?
2021-03-17 14:32:26
有些人真的想证明回调地狱的存在。这对于 LARGE blob 是有意义的,但对于正常用例,JavaScript 应该提供同步方法。
2021-03-18 14:32:26
仅供参考,await blob.arrayBuffer()现在有很好的支持:developer.mozilla.org/en-US/docs/Web/API/Blob/...
2021-04-01 14:32:26
@HenleyChiu 我编辑了答案以包含代码的简短版本。较长的示例旨在完全独立(展示如何创建 ArrayBuffer、Blob,然后再返回)。在不使用Web WorkerFileReaderSync 的情况下,我无法找到读取 Blob 的同步方法
2021-04-07 14:32:26

所述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与较旧的(古老的)浏览器不兼容,因此请查看浏览器兼容性表以确保安全;)

仅供参考,await blob.arrayBuffer()现在有很好的支持:developer.mozilla.org/en-US/docs/Web/API/Blob/...
2021-03-26 14:32:26
咳咳,看来确实是抄袭了。如果斑点很大,那就不好了!
2021-04-01 14:32:26
@GaryO 还没有对它进行基准测试,我假设它复制了 blob 并返回了一个视图。
2021-04-02 14:32:26
这有什么表现?它是复制 Blob 中的数据还是仅返回它的视图?
2021-04-09 14:32:26
巧妙的技巧,不要与Blob.arrayBuffer()即使在 2020 年也具有相当差的兼容性混淆caniuse.com/#feat=mdn-api_blob_arraybufferdeveloper.mozilla.org/en-US/docs/Web/API/Blob/arrayBuffer
2021-04-11 14:32:26

或者你可以使用 fetch API

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

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

或者await blob.arrayBuffer()现在有很好的支持:developer.mozilla.org/en-US/docs/Web/API/Blob/...
2021-03-24 14:32:26
要不就new Response(blob).arrayBuffer()
2021-03-26 14:32:26

只是为了补充@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);

await blob.arrayBuffer() 很好。

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

Blob.prototype.arrayBuffer ??=function(){ return new Response(this).arrayBuffer() }
并且在 IE 中仍然需要 FileReader。我的观点是,您的回答并没有提供比之前的回答更多的内容。如果你想构建一个 polyfill,完成相同任务的所有各种方法都已经存在。
2021-03-18 14:32:26
@Kaiido,IE 要求很少见。¶ 是的,这是 polyfill 的唯一答案。
2021-03-19 14:32:26
@Kaiido,见stackoverflow.com/questions/15341912/...我的方法更胜一筹,在 iOS 支持之前是必需的。(之后可以简单地删除该行)
2021-04-07 14:32:26
stackoverflow.com/a/51758200/3702797和所有其他后备已经存在。
2021-04-08 14:32:26