正如Evert所说,我应该先检查文档中的构建说明
https://stuk.github.io/jszip/documentation/contributing.html
.
很明显,第一个需要git并生成本地克隆。然后需要设置grunt命令行,这需要npm,它与nodejs一起提供。一旦Grunt运行,还有其他的依赖项需要安装NPM。这是通常的小事情关闭和不工作,但足够的瞪大眼睛和蛮力重试来完成。
现在jszip/lib/index.js包含最终导出的资源。它是jszip对象。因此,为了处理内部内容,我可以将这些内容添加到jszip对象中,例如,它已经包含:
JSZip.external = require("./external");
module.exports = JSZip;
因此,我们可以轻松地添加其他要使用的资源:
JSZip.flate = require("./flate");
JSZip.DataWorker = require('./stream/DataWorker');
JSZip.DataLengthProbe = require('./stream/DataLengthProbe');
JSZip.Crc32Probe = require('./stream/Crc32Probe');
JSZip.StreamHelper = require('./stream/StreamHelper');
JSZip.pako = require("pako");
现在,我可以在chrome调试器中创建概念验证:
(new JSZip.StreamHelper(
(new JSZip.DataWorker(Promise.resolve("Hello World! Hello World! Hello World! Hello World! Hello World! Hello World!")))
.pipe(new JSZip.DataLengthProbe("uncompressedSize"))
.pipe(new JSZip.Crc32Probe())
.pipe(JSZip.flate.compressWorker({}))
.pipe(new JSZip.DataLengthProbe("compressedSize"))
.on("end", function(event) { console.log("onEnd: ", this.streamInfo) }),
"uint8array", "")
).accumulate(function(data) { console.log("acc: ", data); })
.then(function(data) { console.log("then: ", data); })
这是可行的。我用gzip头和尾把自己变成了gzip文件流,正确地创建了一切。我将jszip/lib/generate/gzip文件worker.js放在下面:
'use strict';
var external = require('../external');
var utils = require('../utils');
var flate = require('../flate');
var GenericWorker = require('../stream/GenericWorker');
var DataWorker = require('../stream/DataWorker');
var StreamHelper = require('../stream/StreamHelper');
var DataLengthProbe = require('../stream/DataLengthProbe');
var Crc32Probe = require('../stream/Crc32Probe');
function GZipFileWorker() {
GenericWorker.call(this, "GZipFileWorker");
this.virgin = true;
}
utils.inherits(GZipFileWorker, GenericWorker);
GZipFileWorker.prototype.processChunk = function(chunk) {
if(this.virgin) {
this.virgin = false;
var headerBuffer = new ArrayBuffer(10);
var headerView = new DataView(headerBuffer);
headerView.setUint16(0, 0x8b1f, true);
headerView.setUint8(2, 0x08);
headerView.setUint8(3, 0x00);
headerView.setUint32(4, (new Date()).getTime()/1000>>>0, true);
headerView.setUint8(8, 0x00);
headerView.setUint8(9, 0x03);
this.push({data: new Uint8Array(headerBuffer)});
}
this.push(chunk);
};
GZipFileWorker.prototype.flush = function() {
var trailerBuffer = new ArrayBuffer(8);
var trailerView = new DataView(trailerBuffer);
trailerView.setUint32(0, this.streamInfo["crc32"]>>>0, true);
trailerView.setUint32(4, this.streamInfo["originalSize"]>>>0 & 0xffffffff, true);
this.push({data: new Uint8Array(trailerBuffer)});
};
exports.gzip = function(data, inputFormat, outputFormat, compressionOptions, onUpdate) {
var mimeType = data.contentType || data.mimeType || "";
if(! (data instanceof GenericWorker)) {
inputFormat = (inputFormat || "").toLowerCase();
data = new DataWorker(
utils.prepareContent(data.name || "gzip source",
data,
inputFormat !== "string",
inputFormat === "binarystring",
inputFormat === "base64"));
}
return new StreamHelper(
data
.pipe(new DataLengthProbe("originalSize"))
.pipe(new Crc32Probe())
.pipe(flate.compressWorker( compressionOptions || {} ))
.pipe(new GZipFileWorker()),
outputFormat.toLowerCase(), mimeType).accumulate(onUpdate);
};
在jszip/lib/index.js中,我只需要:
var gzip = require("./generate/GZipFileWorker");
JSZip.gzip = gzip.gzip;
这样的工作原理是:
JSZip.gzip("Hello World! Hello World! Hello World! Hello World! Hello World! Hello World!", "string", "base64", {level: 3}).then(function(result) { console.log(result); })
我可以将结果粘贴到Unix管道中,如下所示:
$ echo -n "H4sIAOyR/VsAA/NIzcnJVwjPL8pJUVTwoJADAPCORolNAAAA" |base64 -d |zcat
它正确地返回
Hello World! Hello World! Hello World! Hello World! Hello World! Hello World!
它还可以与文件一起使用:
JSZip.gzip(file, "", "Blob").then(function(blob) {
xhr.setRequestProperty("Content-encoding", "gzip");
xhr.send(blob);
})
我可以将blob发送到我的Web服务器。我已经检查过大文件确实是分块处理的。
我唯一不喜欢的是,最后一个blob仍然组装成一个大blob,所以我假设它在内存中保存所有压缩数据。如果该攻击是该工作管道的端点,这样当xhr.send从blob中逐块获取数据时,它将仅在那时使用工作管道中的块。但是,由于它只保存压缩内容,因此影响会大大降低,而且(至少对我而言)大型文件可能是不需要gzip压缩的多媒体文件。
我没有编写gunzip函数,因为坦率地说,我不需要它,也不想让它无法正确解析gzip头中的扩展头。一旦我将压缩内容上传到服务器(在我的例子中是S3),当我再次获取它时,我假设浏览器会为我进行解压缩。不过我还没检查过。如果它成为一个问题,我会回来编辑这个答案更多。
这是我在Github的叉子:
https://github.com/gschadow/jszip
,已输入拉请求。