Распаковка файлов - PullRequest
       21

Распаковка файлов

66 голосов
/ 19 января 2010

Я хочу отобразить OpenOffice файлы, .odt и .odp на стороне клиента с помощью веб-браузера.

Эти файлы являются заархивированными файлами. Используя Ajax, я могу получить эти файлы с сервера, но это заархивированные файлы. Я должен распаковать их, используя JavaScript , я пытался использовать inflate.js, http://www.onicos.com/staff/iz/amuse/javascript/expert/inflate.txt,, но безуспешно.

Как я могу это сделать?

Ответы [ 7 ]

60 голосов
/ 20 января 2010

Я написал молнию на 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.

24 голосов
/ 17 июня 2012

Я использую zip.js , и это кажется весьма полезным. Это стоит посмотреть!

Проверьте демонстрацию Unzip , например.

11 голосов
/ 09 декабря 2014

Я нашел jszip весьма полезным. До сих пор я использовал только для чтения, но у них также есть возможность создавать / редактировать.

Кодекс выглядит примерно так

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

Одна вещь, которую я заметил, это то, что, похоже, файл должен быть в двоичном формате потока (прочитайте с помощью .readAsArrayBuffer из FileReader (), в противном случае я получаю ошибки, говорящие о том, что у меня может быть поврежденный zip-файл

2 голосов
/ 30 октября 2018

Если вам нужна поддержка других форматов или вам нужна хорошая производительность, вы можете использовать эту библиотеку WebAssembly

он основан на обещаниях, он использует WebWorkers для многопоточности, а API на самом деле является простым модулем ES

2 голосов
/ 12 июля 2014

Я написал «Бинарные инструменты для JavaScript», проект с открытым исходным кодом, который включает в себя возможность распаковать, распаковать и распаковать: https://github.com/codedread/bitjs

Используется в моей программе чтения комиксов: https://github.com/codedread/kthoom (также с открытым исходным кодом).

НТН!

2 голосов
/ 07 августа 2011

Я тоже написал класс для этого. http://blog.another -d-mention.ro / программирования / чтения-загрузки-файлов, из-ZIP-в-JavaScript / Вы можете загрузить основные ресурсы, такие как javascript / css / images, прямо из zip-файла, используя методы класса. Надеюсь, это поможет

2 голосов
/ 19 января 2010

Пример кода приведен на сайте автора . Вы можете использовать babelfish для перевода текстов (с японского на английский).

Насколько я понимаю по-японски, этот zip-инфляционный код предназначен для декодирования данных ZIP (потоков), а не ZIP-архива.

...