我使用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需要包装在一个数组中。这是为什么?
答案 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文章在这里几乎是错误的,而且充其量是误导性的。
可以使用以下参数调用Blob()构造函数:
blobParts序列 它采用任意数量的以下类型的元素,并以任何顺序:
BufferSource元素。
Blob elements。
USVString元素。
... [BlobPropertyBag,我们这里没有业务]
所以这里的序列可以是很多东西,从Array
到Set
通过一个多维数组。
然后算法将遍历此序列,直到找到上述三种元素之一。
所以在你的情况下会发生的事情是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);
}