Как говорил Эверт, я должен был сначала проверить инструкции по сборке в документации https://stuk.github.io/jszip/documentation/contributing.html.
Из этого ясно, что сначала нужно git и сделать локальный клон.Затем необходимо настроить командную строку grunt, для которой требуется npm, поставляемый с nodejs.После запуска grunt появляются другие зависимости, которые необходимо установить npm.Это обычные мелочи, и они не работают, но достаточно Googling и грубой силы, которые пытаются это сделать.
Теперь 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); })
, и это работает.Я делаю себе GZipFileStream с заголовком gzip и трейлером, создавая все правильно.Я помещаю jszip / lib / generate / GZipFileWorker.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); // GZip magic
headerView.setUint8(2, 0x08); // compression algorithm DEFLATE
headerView.setUint8(3, 0x00); // flags
// bit 0 FTEXT
// bit 1 FHCRC
// bit 2 FEXTRA
// bit 3 FNAME
// bit 4 FCOMMENT
headerView.setUint32(4, (new Date()).getTime()/1000>>>0, true);
headerView.setUint8(8, 0x00); // no extension headers
headerView.setUint8(9, 0x03); // OS type UNIX
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-объект все еще собран как один большой BLOB-объект, поэтому я предполагаю, что он хранит все сжатые данные в памяти.Было бы лучше, если бы этот Blow был конечной точкой этого конвейера Worker, чтобы, когда xhr.send собирал данные из BLOB-объекта в виде фрагментов, только тогда он получал бы фрагменты из конвейера Worker.Тем не менее, влияние значительно уменьшается, учитывая, что он содержит только сжатый контент, и, вероятно, большие (по крайней мере, для меня) файлы будут мультимедийными, и в любом случае их не нужно будет сжать gzip.
IЯ не написал функцию gunzip, потому что, честно говоря, мне она не нужна, и я не хочу создавать такую, которая не сможет правильно анализировать заголовки расширений в заголовках gzip.Как только я загрузил сжатый контент на сервер (в моем случае S3), когда я получаю его снова, я предполагаю, что браузер выполнит распаковку для меня.Я не проверял это все же.Если это станет проблемой, я вернусь и отредактирую этот ответ подробнее.
Вот мой форк на github: https://github.com/gschadow/jszip, запрос на ввод уже введен.