2010-01-19 7 views
57

Ich möchte OpenOffice Dateien, ODT und ODP auf Client-Seite mit einem Webbrowser anzeigen.Entpacken von Dateien

Diese Dateien sind gezippte Dateien. Mit Ajax kann ich diese Dateien vom Server beziehen, aber das sind gezippte Dateien. Ich muss sie entpacken mit JavaScript, ich habe versucht, mit inflate.js, http://www.onicos.com/staff/iz/amuse/javascript/expert/inflate.txt, aber ohne Erfolg.

Wie kann ich das tun?

+4

"kein Erfolg" bitte seien Sie spezifischer, zeigen Sie uns einige Code, zeigen Sie uns einige Fehler ... Wir sind hier, um zu helfen, nicht zu erraten. – OcuS

+0

Grundsätzlich habe ich einfach aufgeblasen Funktion - data = zip_inflate (src); Aber ich denke, das ist für einzelne Datei gemeint. Wenn ein zi p-Dateien enthalten mehrere Dateien in einer Verzeichnisstruktur, dann was ist der Inhalt von "Daten". Ich weiß nicht, wie man diese Bibliothek benutzt. – user69260

+0

@Eimantas Was bedeutet das? + Oder - – user69260

Antwort

59

Ich schrieb einen Entpacker in Javascript. Es klappt.

Es beruht auf Andy G.P. Na's binary file reader und some RFC1951 inflate logic from 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 enthalten ist eine ZipFile.htm-Demoseite und drei verschiedene Skripts, eines für die ZIP-Dateiklasse, eines für die Inflate-Klasse und eines für eine Binärdatei-Leserklasse. Die Demo hängt auch von jQuery und jQuery UI ab. Wenn Sie nur die Datei js-zip.zip herunterladen, sind alle erforderlichen Quellen vorhanden.


Hier ist, was der Anwendungscode wie in Javascript aussieht:

// In my demo, this gets attached to a click event. 
// it instantiates a ZipFile, and provides a callback that is 
// invoked when the zip is read. This can take a few seconds on a 
// large zip file, so it's asynchronous. 
var readFile = function(){ 
    $("#status").html("<br/>"); 
    var url= $("#urlToLoad").val(); 
    var doneReading = function(zip){ 
     extractEntries(zip); 
    }; 

    var zipFile = new ZipFile(url, doneReading); 
}; 


// this function extracts the entries from an instantiated zip 
function extractEntries(zip){ 
    $('#report').accordion('destroy'); 

    // clear 
    $("#report").html(''); 

    var extractCb = function(id) { 
     // this callback is invoked with the entry name, and entry text 
     // in my demo, the text is just injected into an accordion panel. 
     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 each entry in the zip, extract it. 
    for (var i=0; i<zip.entries.length; i++) { 
     var entry = zip.entries[i]; 

     var entryInfo = "<h4><a>" + entry.name + "</a></h4>\n<div>"; 

     // contrive an id for the entry, make it unique 
     var randomId = "id-"+ Math.floor((Math.random() * 1000000000)); 

     entryInfo += "<span class='inputDiv'><h4>Content:</h4><span id='" + randomId + 
      "'></span></span></div>\n"; 

     // insert the info for one entry as the last child within the report div 
     $("#report").append(entryInfo); 

     // extract asynchronously 
     entry.extract(extractCb(randomId)); 
    } 
} 

Die Demo in ein paar Schritten arbeitet: Die readFile fn durch einen Klick ausgelöst wird, und instanziiert ein ZipFile Objekt , die die Zip-Datei liest. Es gibt einen asynchronen Callback für den Abschluss des Lesevorgangs (normalerweise in weniger als einer Sekunde für sinnvoll dimensionierte Zips) - in dieser Demo wird der Callback in der lokalen Variablen doneReading gehalten, die einfach extractEntries aufruft, die den gesamten Inhalt blind entpackt die bereitgestellte Zip-Datei. In einer echten App würden Sie wahrscheinlich einige der zu extrahierenden Einträge auswählen (dem Benutzer erlauben, auszuwählen oder einen oder mehrere Einträge programmgesteuert auszuwählen, usw.).

Die extractEntries Fn iteriert über alle Einträge und ruft jeweils extract() auf, wobei ein Callback übergeben wird. Die Dekomprimierung eines Eintrags benötigt Zeit, vielleicht 1s oder mehr für jeden Eintrag in der Zip-Datei, was bedeutet, dass Asynchronität angemessen ist. Der Extract-Callback fügt den extrahierten Inhalt einfach zu 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 begrenzt ist.

Zum einen: Es ist sehr langsam. Nimmt ~ 4 Sekunden zum Entpacken des 140k AppNote.txt-Datei von PKWare. Die gleiche Dekomprimierung kann in weniger als 0,5 s in einem .NET-Programm durchgeführt werden. EDIT: Die Javascript ZipFile entpackt wesentlich schneller als jetzt, in IE9 und in Chrome. Es ist immer noch langsamer als ein kompiliertes Programm, aber es ist viel schneller für die normale Browsernutzung.

Zum anderen: es tut nicht Streaming. Es schlürft grundsätzlich den gesamten Inhalt der Zip-Datei in den Speicher. In einer "echten" Programmierumgebung könnten Sie nur die Metadaten einer Zip-Datei (z. B. 64 Bytes pro Eintrag) einlesen und dann die anderen Daten wie gewünscht lesen und dekomprimieren. Es gibt keine Möglichkeit, IO in JavaScript zu machen, so weit ich weiß, daher ist die einzige Möglichkeit, die gesamte Zip in den Speicher zu lesen und wahllos darauf zuzugreifen. Das bedeutet, dass der Systemspeicher für große ZIP-Dateien unangemessen hohe Anforderungen stellt. Nicht so ein Problem für eine kleinere Zip-Datei.

Auch: Es funktioniert nicht die "allgemeine Fall" Zip-Datei - es gibt viele Zip-Optionen, die ich nicht in den Unzipper implementieren - wie ZIP-Verschlüsselung, WinZip-Verschlüsselung, Zip64, UTF-8 kodierte Dateinamen, und so weiter. (EDIT - es handhabt jetzt UTF-8 codierte Dateinamen). Die ZipFile-Klasse behandelt jedoch die Grundlagen. Einige dieser Dinge wären nicht schwer zu implementieren. Ich habe an AES encryption class in Javascript; das könnte integriert werden, um die Verschlüsselung zu unterstützen. Die Unterstützung von Zip64 würde wahrscheinlich für die meisten Benutzer von Javascript nutzlos sein, da es> 4GB-ZIP-Dateien unterstützen soll - diese müssen nicht in einem Browser extrahiert werden.

Ich habe auch nicht den Fall für das Entpacken binärer Inhalte getestet. Im Moment entzippt es den Text. Wenn Sie eine gezippte Binärdatei haben, müssten Sie die ZipFile-Klasse bearbeiten, um sie richtig zu handhaben. Ich habe nicht herausgefunden, wie ich das sauber machen soll. Es tut jetzt auch binäre Dateien.


EDIT - ich die JS unzip Bibliothek und Demo aktualisiert. Es tut jetzt Binärdateien, zusätzlich zu Text. Ich habe es widerstandsfähiger und allgemeiner gemacht - Sie können jetzt die Codierung angeben, die beim Lesen von Textdateien verwendet werden soll. Auch das Demo ist erweitert - es zeigt unter anderem das Entpacken einer XLSX-Datei im Browser.

Also, während ich denke, dass es von begrenztem Nutzen und Interesse ist, funktioniert es. Ich denke, es würde in Node.js funktionieren.

+1

Cheeso: :) :) Gibt es irgendwo einen Blick darauf? –

+0

Ja, ich habe die Antwort bearbeitet und Links hinzugefügt. – Cheeso

+0

Das sieht gut aus, aber ich habe diese Fehlermeldung: Diese ZIP-Datei verwendet UTF8, die nicht von ZipFile.js unterstützt wird. Jede schnelle Abhilfe, die Sie empfehlen können? –

2

Codebeispiel ist on the author site's. Sie können babelfish verwenden, um die Texte zu übersetzen (Japanisch nach Englisch).

Soweit ich Japanisch verstehe, soll dieser Zip-Inflate-Code ZIP-Daten (Streams) nicht als ZIP-Archiv dekodieren.

22

Ich benutze zip.js und es scheint sehr nützlich zu sein. Es ist einen Blick wert!

Überprüfen Sie zum Beispiel die Unzip demo.

+0

ich benutze die zip.js die gleiche wie du benutzt, aber in Safari bekomme ich den Filereader nicht definiert.pls helfen mir bei der Arbeit mit Safari. – user969275

+0

Ich habe keine Erfahrung mit Safari. Sie sollten die zip.js Entwickler fragen. Unten auf der Projektseite befindet sich eine E-Mail-Adresse: http://gildas-lormeau.github.com/zip.js/. Vielleicht ist es ein Fehler, also werden sie sich für die Benachrichtigung bedanken. –

+0

Danke für die Antwort, ich habe ein Problem veröffentlicht. – user969275

6

Ich fand jszip ziemlich nützlich. Ich habe bisher nur zum Lesen verwendet, aber sie haben auch erstellen/bearbeiten Fähigkeiten.

-Code weise sieht es so etwas wie dieses Ich

var new_zip = new JSZip(); 
new_zip.load(file); 
new_zip.files["doc.xml"].asText() // this give you the text in the file 

Eine Sache aufgefallen ist, dass es die Datei scheint im binären Stream-Format zu sein hat (lesen Sie die .readAsArrayBuffer von Filereader() verwenden, sonst war ich immer Fehler sagen, dass ich eine korrupte ZIP-Datei haben könnte

+1

Das hat mir geholfen. Vielen Dank. :) – deekshith