Napisałem unzipper w Javascript. To działa.
Opiera się na czytniku plików binarnych Andy GP Na i logice inflacji RFC1951 z notmasteryet . Dodałem klasę ZipFile.
działający przykład:
http://cheeso.members.winisp.net/Unzip-Example.htm (martwy link)
Źródło:
http://cheeso.members.winisp.net/srcview.aspx?dir=js-unzip (martwy link)
Uwaga : linki są martwe; Niedługo znajdę nowego gospodarza.
W źródle znajduje się strona demonstracyjna ZipFile.htm oraz 3 różne skrypty, jeden dla klasy zipfile, jeden dla klasy inflate i jeden dla klasy czytnika plików binarnych. Demo zależy również od interfejsu użytkownika jQuery i jQuery. Jeśli po prostu pobierzesz plik js-zip.zip, znajdziesz tam całe potrzebne źródło.
Oto jak wygląda kod aplikacji w JavaScript:
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));
}
}
Demo działa w kilku krokach: readFile
fn jest wyzwalany przez kliknięcie i tworzy instancję obiektu ZipFile, który odczytuje plik zip. Istnieje asynchroniczne wywołanie zwrotne po zakończeniu odczytu (zwykle dzieje się to w mniej niż sekundę dla zamków błyskawicznych o rozsądnych rozmiarach) - w tym demie wywołanie zwrotne jest przechowywane w zmiennej lokalnej doneReading, która po prostu wywołuje extractEntries
, która po prostu ślepo rozpakowuje całą zawartość podanego plik zip. W prawdziwej aplikacji prawdopodobnie wybrałbyś niektóre wpisy do wyodrębnienia (pozwoliłbyś użytkownikowi wybrać lub wybrać programowo jeden lub więcej wpisów itp.).
W extractEntries
fn iteracje nad wszystkimi wpisami, a rozmowy extract()
na temat każdego z nich, mijając zwrotnego. Dekompresja wpisu zajmuje trochę czasu, może 1 s lub więcej dla każdego wpisu w pliku zip, co oznacza, że asynchronia jest odpowiednia. Wyodrębnianie wywołania zwrotnego po prostu dodaje wyodrębnioną zawartość do akordeonu jQuery na stronie. Jeśli zawartość jest binarna, zostanie odpowiednio sformatowana (nie pokazana).
Działa, ale myślę, że narzędzie jest nieco ograniczone.
Po pierwsze: jest bardzo powolny. Rozpakowanie 140k pliku AppNote.txt z PKWare zajmuje około 4 sekund. To samo rozpakowanie można wykonać w czasie krótszym niż .5s w programie .NET. EDYCJA : Javascript ZipFile rozpakowuje się znacznie szybciej niż teraz, w IE9 i Chrome. Jest nadal wolniejszy niż program skompilowany, ale jest wystarczająco szybki dla normalnego użytkowania przeglądarki.
Po drugie: nie obsługuje przesyłania strumieniowego. Zasadniczo siorbi całą zawartość pliku zip do pamięci. W „prawdziwym” środowisku programistycznym można było wczytać tylko metadane pliku zip (powiedzmy 64 bajty na wpis), a następnie odczytać i rozpakować inne dane według potrzeb. O ile wiem, nie ma sposobu, aby zrobić takie IO w javascript, dlatego jedyną opcją jest wczytanie całego pliku zip do pamięci i zrobienie w nim swobodnego dostępu. Oznacza to, że duże pliki zip będą wymagały nieracjonalnego wykorzystania pamięci systemowej. Nie jest to duży problem w przypadku mniejszego pliku zip.
Ponadto: nie obsługuje pliku zip „ogólnego przypadku” - istnieje wiele opcji zip, których nie zawracałem sobie głowy zaimplementowaniem w rozpakowywaczu - takie jak szyfrowanie ZIP, szyfrowanie WinZip, zip64, zakodowane nazwy plików w formacie UTF-8 itd. na. ( EDYCJA - teraz obsługuje nazwy plików zakodowane w UTF-8). Klasa ZipFile obsługuje jednak podstawy. Niektóre z tych rzeczy nie byłyby trudne do wdrożenia. Mam klasę szyfrowania AES w JavaScript; które można by zintegrować w celu obsługi szyfrowania. Obsługa Zip64 byłaby prawdopodobnie bezużyteczna dla większości użytkowników Javascript, ponieważ jest przeznaczona do obsługi plików zip> 4 GB - nie trzeba ich rozpakowywać w przeglądarce.
Nie testowałem też przypadku rozpakowywania zawartości binarnej. W tej chwili rozpakowuje tekst. Jeśli masz spakowany plik binarny, musisz edytować klasę ZipFile, aby poprawnie go obsłużyć. Nie wymyśliłem, jak to zrobić czysto. Teraz obsługuje również pliki binarne.
EDYCJA - zaktualizowałem bibliotekę rozpakowywania JS i wersję demonstracyjną. Teraz oprócz tekstu obsługuje pliki binarne. Uczyniłem go bardziej odpornym i bardziej ogólnym - możesz teraz określić kodowanie, które ma być używane podczas czytania plików tekstowych. Rozbudowano również demo - pokazuje m.in. rozpakowywanie pliku XLSX w przeglądarce.
Tak więc, chociaż myślę, że ma ograniczoną użyteczność i zainteresowanie, działa. Myślę, że zadziałaby w Node.js.