为什么Array的Blob小于Uint8Array的Blob?

时间:2018-03-29 09:29:41

标签: javascript blob arraybuffer uint8array

我使用FileReader.readAsArrayBuffer读取文件,然后执行以下操作:

  var compressedData = pako.gzip(new Uint8Array(this.result));
  var blob1 = new Blob([compressedData]); // size = 1455338 bytes
  var blob2 = new Blob(compressedData);   // size = 3761329 bytes

举个例子:如果结果有4194304个字节,压缩后它的大小为1455338个字节。但由于某种原因,Uint8Array需要包装在一个数组中。这是为什么?

2 个答案:

答案 0 :(得分:2)

比照。 BLOB构造函数的文档:

https://developer.mozilla.org/en-US/docs/Web/API/Blob/Blob

  

[第一个参数]是一个ArrayBuffer,ArrayBufferView,Blob,DOMString对象的数组,或任何这些对象的混合,将放在Blob中。 DOMStrings编码为UTF-8。

我不知道它是如何工作的,但基本上构造函数需要一些它将打包到BLOB中的东西。因此,在第一种情况下,您构建单个部件的BLOB(即您的ArrayBuffer),而在第二种情况下,您将从1455338个部件(即每个字节分别)构建它。

由于文档说BLOB部分只能是数组或字符串,它可能最终将ArrayBuffer中的每个字节值转换为UTF-8字符串,这意味着它不使用每个数字1个字节,而是使用1个字节每十进制数字(两个结果大小的比率似乎支持这一点,因为单字节值是1-3位长,而较大的BLOB大约是较小的2.5倍)。这不仅浪费,我还很确定它也会使您的ZIP无法使用。

所以,最重要的是,第一个版本是正确的方法。

答案 1 :(得分:1)

不幸的是,MDN文章在这里几乎是错误的,而且充其量是误导性的。

From the specs

  

可以使用以下参数调用Blob()构造函数:

     
      
  • blobParts序列   它采用任意数量的以下类型的元素,并以任何顺序:

         
        
    • BufferSource元素。

    •   
    • Blob elements。

    •   
    • USVString元素。

    •   
  •   
  • ... [BlobPropertyBag,我们这里没有业务]

  •   

所以这里的序列可以是很多东西,从ArraySet通过一个多维数组。

然后算法将遍历此序列,直到找到上述三种元素之一。

所以在你的情况下会发生的事情是TypedArray 可以转换为序列。这意味着当你将它作为直接参数传递时,它将无法看到它的ArrayBuffer ,算法将遍历其内容并获取值(此处8位数转换为字符串),这可能不是你所期望的。

另一方面,当您通过数组包装Uint8Array时,算法能够找到您的Uint8Array指向的BufferSource。所以它将使用它(二进制数据,可能你想要的)。

var arr = new Uint8Array(25);
arr.fill(255);
var nowrap = new Blob(arr);
var wrapped = new Blob([arr]);
test(nowrap, 'no wrap');
test(wrapped, 'wrapped');

function test(blob, msg) {
  var reader = new FileReader();
  reader.onload = e => console.log(msg, reader.result);
  reader.readAsText(blob);
}