Я написал распаковщик на Javascript. Оно работает.
Он опирается на Andy G.P. Средство чтения двоичных файлов Na и некоторые RFC1951 раздувают логику notmasteryet. Я добавил класс ZipFile.
рабочий пример:
http://cheeso.members.winisp.net/Unzip-Example.htm (мертвая ссылка)
Источник:
http://cheeso.members.winisp.net/srcview.aspx?dir=js-unzip (неработающая ссылка)
Примечание: ссылки не работают; Я скоро найду нового хозяина.
В исходный код включена демонстрационная страница ZipFile.htm и 3 отдельных сценария: один для класса zipfile, один для класса inflate и один для класса чтения двоичных файлов. Демонстрация также зависит от jQuery и пользовательского интерфейса jQuery. Если вы просто загрузите файл js-zip.zip, все необходимые исходники уже есть.
Вот как выглядит код приложения в Javascript:
// 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));
}
}
Демонстрация работает в несколько шагов: readFile
fn запускается щелчком мыши и создает экземпляр объекта ZipFile, который считывает zip-файл. Существует асинхронный обратный вызов для завершения чтения (обычно это происходит менее чем за секунду для почтовых индексов разумного размера) — в этой демонстрации обратный вызов хранится в локальной переменной doneReading, которая просто вызывает extractEntries
, которая просто слепо распаковывает все содержимое файла. предоставил zip-файл. В реальном приложении вы, вероятно, выбрали бы некоторые записи для извлечения (разрешить пользователю выбирать или выбирать одну или несколько записей программно и т. д.).
extractEntries
fn выполняет итерацию по всем записям и вызывает extract()
для каждой из них, передавая обратный вызов. Распаковка записи занимает время, может быть, 1 с или более для каждой записи в zip-файле, что означает, что асинхронность подходит. Обратный вызов extract просто добавляет извлеченный контент в аккордеон jQuery на странице. Если содержимое двоичное, оно форматируется как таковое (не показано).
Это работает, но я думаю, что полезность несколько ограничена.
Во-первых, это очень медленно. Распаковка файла AppNote.txt размером 140 КБ из PKWare занимает ~4 секунды. То же самое распаковка может быть выполнена менее чем за 0,5 секунды в программе .NET. EDIT: Javascript ZipFile распаковывается значительно быстрее, чем сейчас, в IE9 и Chrome. Это все еще медленнее, чем скомпилированная программа, но достаточно быстро для обычного использования браузера.
Для другого: он не занимается потоковой передачей. В основном он загружает все содержимое zip-файла в память. В «реальной» среде программирования вы могли бы прочитать только метаданные zip-файла (скажем, 64 байта на запись), а затем прочитать и распаковать другие данные по желанию. Насколько мне известно, в javascript нет возможности сделать такой ввод-вывод, поэтому единственный вариант - прочитать весь zip в память и сделать в нем произвольный доступ. Это означает, что он будет предъявлять необоснованные требования к системной памяти для больших zip-файлов. Не такая большая проблема для меньшего zip-файла.
Кроме того: он не обрабатывает zip-файл «общего случая» — есть много параметров zip, которые я не удосужился реализовать в распаковщике — например, шифрование ZIP, шифрование WinZip, zip64, имена файлов в кодировке UTF-8. , и так далее. (EDIT — теперь он обрабатывает имена файлов в кодировке UTF-8). Однако класс ZipFile обрабатывает основы. Некоторые из этих вещей было бы нетрудно реализовать. У меня есть класс шифрования AES в Javascript; которые могут быть интегрированы для поддержки шифрования. Поддержка Zip64, вероятно, будет бесполезна для большинства пользователей Javascript, поскольку она предназначена для поддержки zip-файлов > 4 ГБ - не нужно извлекать их в браузере.
Я также не проверял возможность распаковки бинарного содержимого. Прямо сейчас он распаковывает текст. Если у вас есть заархивированный двоичный файл, вам нужно отредактировать класс ZipFile, чтобы он правильно обрабатывался. Я не понял, как это сделать чисто. Теперь он работает и с бинарными файлами.
EDIT. Я обновил библиотеку распаковки JS и демо. Теперь он делает двоичные файлы, в дополнение к тексту. Я сделал его более устойчивым и более общим — теперь вы можете указать кодировку, которую следует использовать при чтении текстовых файлов. Также демонстрация расширена — она показывает, среди прочего, распаковку XLSX-файла в браузере.
Итак, хотя я думаю, что это имеет ограниченную полезность и интерес, это работает. Я думаю, это сработает в Node.js.
person
Community
schedule
19.01.2010