Ich habe einen Entpacker in Javascript geschrieben. Es klappt.
Es basiert auf dem Binärdateireader von Andy GP Na und einer RFC1951-Aufblaslogik von notmasteryet . Ich habe die ZipFile-Klasse hinzugefügt.
Arbeitsbeispiel:
http://cheeso.members.winisp.net/Unzip-Example.htm (toter Link)
Die Quelle:
http://cheeso.members.winisp.net/srcview.aspx?dir=js-unzip (toter Link)
NB : Die Links sind tot. Ich werde bald einen neuen Gastgeber finden.
In der Quelle sind eine ZipFile.htm-Demonstrationsseite und drei verschiedene Skripte enthalten, eines für die Zipfile-Klasse, eines für die Inflate-Klasse und eines für eine Binärdateireaderklasse. Die Demo hängt auch von jQuery und der jQuery-Benutzeroberfläche ab. Wenn Sie nur die Datei js-zip.zip herunterladen, ist die gesamte erforderliche Quelle vorhanden.
So sieht der Anwendungscode in Javascript aus:
var readFile = function(){
$("#status").html("<br/>");
var url= $("#urlToLoad").val();
var doneReading = function(zip){
extractEntries(zip);
};
var zipFile = new ZipFile(url, doneReading);
};
function extractEntries(zip){
$('#report').accordion('destroy');
$("#report").html('');
var extractCb = function(id) {
return (function(entryName, entryText){
var content = entryText.replace(new RegExp( "\\n", "g" ), "<br/>");
$("#"+id).html(content);
$("#status").append("extract cb, entry(" + entryName + ") id(" + id + ")<br/>");
$('#report').accordion('destroy');
$('#report').accordion({collapsible:true, active:false});
});
}
for (var i=0; i<zip.entries.length; i++) {
var entry = zip.entries[i];
var entryInfo = "<h4><a>" + entry.name + "</a></h4>\n<div>";
var randomId = "id-"+ Math.floor((Math.random() * 1000000000));
entryInfo += "<span class='inputDiv'><h4>Content:</h4><span id='" + randomId +
"'></span></span></div>\n";
$("#report").append(entryInfo);
entry.extract(extractCb(randomId));
}
}
Die Demo funktioniert in wenigen Schritten: Das readFile
fn wird durch einen Klick ausgelöst und instanziiert ein ZipFile-Objekt, das die Zip-Datei liest. Es gibt einen asynchronen Rückruf, wenn der Lesevorgang abgeschlossen ist (normalerweise in weniger als einer Sekunde bei Zips mit angemessener Größe). In dieser Demo wird der Rückruf in der lokalen Variablen doneReading gehalten, die einfach aufruft extractEntries
und den gesamten Inhalt des bereitgestellten einfach blind entpackt zip-Datei. In einer echten App würden Sie wahrscheinlich einige der zu extrahierenden Einträge auswählen (dem Benutzer erlauben, einen oder mehrere Einträge programmgesteuert auszuwählen usw.).
Das extractEntries
fn durchläuft alle Einträge und ruft extract()
jeden auf, wobei ein Rückruf weitergeleitet wird. Die Dekomprimierung eines Eintrags benötigt Zeit, möglicherweise 1s oder mehr für jeden Eintrag in der Zip-Datei, was bedeutet, dass Asynchronität angemessen ist. Der Rückruf zum Extrahieren fügt den extrahierten Inhalt einfach einem jQuery-Akkordeon auf der Seite hinzu. Wenn der Inhalt binär ist, wird er als solcher formatiert (nicht gezeigt).
Es funktioniert, aber ich denke, dass das Dienstprogramm etwas eingeschränkt ist.
Zum einen: Es ist sehr langsam. Das Entpacken der 140k-Datei AppNote.txt aus PKWare dauert ca. 4 Sekunden. Die gleiche Dekomprimierung kann in einem .NET-Programm in weniger als 0,5 Sekunden durchgeführt werden. EDIT : Die Javascript ZipFile auspackt deutlich schneller als das jetzt, in IE9 und in Chrome. Es ist immer noch langsamer als ein kompiliertes Programm, aber für die normale Verwendung des Browsers ist es schnell genug.
Zum anderen: Es wird kein Streaming durchgeführt. Es schlürft im Grunde den gesamten Inhalt der Zip-Datei in den Speicher. In einer "echten" Programmierumgebung können Sie nur die Metadaten einer Zip-Datei einlesen (z. B. 64 Byte pro Eintrag) und dann die anderen Daten wie gewünscht lesen und dekomprimieren. Soweit ich weiß, gibt es keine Möglichkeit, solche E / A-Vorgänge in Javascript durchzuführen. Daher besteht die einzige Möglichkeit darin, die gesamte Zip-Datei in den Speicher einzulesen und wahlfrei darauf zuzugreifen. Dies bedeutet, dass für große Zip-Dateien unangemessene Anforderungen an den Systemspeicher gestellt werden. Für eine kleinere Zip-Datei kein Problem.
Außerdem: Die Zip-Datei "Allgemein" wird nicht behandelt. Es gibt viele Zip-Optionen, die ich nicht im Unzipper implementiert habe - wie ZIP-Verschlüsselung, WinZip-Verschlüsselung, zip64, UTF-8-codierte Dateinamen usw. auf. ( BEARBEITEN - es verarbeitet jetzt UTF-8-codierte Dateinamen). Die ZipFile-Klasse übernimmt jedoch die Grundlagen. Einige dieser Dinge wären nicht schwer zu implementieren. Ich habe eine AES-Verschlüsselungsklasse in Javascript. das könnte integriert werden, um die Verschlüsselung zu unterstützen. Die Unterstützung von Zip64 wäre für die meisten Benutzer von Javascript wahrscheinlich nutzlos, da es beabsichtigt, Zip-Dateien mit> 4 GB zu unterstützen - Sie müssen diese nicht in einem Browser extrahieren.
Ich habe den Fall auch nicht zum Entpacken von binären Inhalten getestet. Im Moment wird der Text entpackt. Wenn Sie eine komprimierte Binärdatei haben, müssen Sie die ZipFile-Klasse bearbeiten, um sie ordnungsgemäß zu verarbeiten. Ich habe nicht herausgefunden, wie ich das sauber machen soll. Es macht jetzt auch Binärdateien.
BEARBEITEN - Ich habe die JS-Entpackungsbibliothek und die Demo aktualisiert. Zusätzlich zum Text werden jetzt Binärdateien ausgeführt. Ich habe es widerstandsfähiger und allgemeiner gemacht - Sie können jetzt die Codierung angeben, die beim Lesen von Textdateien verwendet werden soll. Auch die Demo wird erweitert - sie zeigt unter anderem das Entpacken einer XLSX-Datei im Browser.
Obwohl ich denke, dass es von begrenztem Nutzen und Interesse ist, funktioniert es. Ich denke, es würde in Node.js funktionieren.