Я написал молнию на Javascript. Оно работает.
Он опирается на Энди Г.П. Читатель двоичных файлов На и некоторые RFC1951 раздувают логику из notmasteryet . Я добавил класс ZipFile.
рабочий пример:
http://cheeso.members.winisp.net/Unzip-Example.htm (неработающая ссылка)
Источник:
http://cheeso.members.winisp.net/srcview.aspx?dir=js-unzip (неработающая ссылка)
NB : ссылки не работают; Я скоро найду нового хозяина.
В исходный код включена демонстрационная страница ZipFile.htm и 3 различных сценария, один для класса zipfile, один для класса inflate и один для класса чтения двоичных файлов. Демонстрация также зависит от jQuery и jQuery UI. Если вы просто загрузите файл 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 на странице. Если содержимое является двоичным, то оно форматируется как таковое (не показано).
Это работает, но я думаю, что утилита несколько ограничена.
С одной стороны: это очень медленно. Требуется ~ 4 секунды, чтобы распаковать файл 140K AppNote.txt из PKWare. Такое же распаковывание может быть сделано менее чем за 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, поскольку она предназначена для поддержки> 4 ГБ zip-файлов - не нужно извлекать их в браузере.
Я также не проверял случай для разархивирования двоичного содержимого. Прямо сейчас это распаковывает текст. Если у вас есть заархивированный двоичный файл, вам нужно отредактировать класс ZipFile для правильной обработки. Я не понял, как сделать это чисто. Теперь он также выполняет двоичные файлы.
EDIT - Я обновил библиотеку JS unzip и демонстрацию.Это теперь делает двоичные файлы, в дополнение к тексту.Я сделал его более гибким и общим - теперь вы можете указать кодировку, используемую при чтении текстовых файлов.Также расширена демонстрационная версия - она показывает, среди прочего, разархивирование файла XLSX в браузере.
Итак, хотя я думаю, что он имеет ограниченную полезность и интерес, он работает.Я думаю, это будет работать в Node.js.