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

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

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

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


person user69260    schedule 19.01.2010    source источник
comment
нет успеха, пожалуйста, будьте более конкретными, покажите нам код, покажите нам некоторые ошибки... мы здесь, чтобы помочь, а не гадать.   -  person OcuS    schedule 19.01.2010
comment
По сути, я просто вызвал функцию надувания - data = zip_inflate(src); Но я думаю, что это предназначено для одного файла. Если zip-файлы содержат несколько файлов в структуре каталогов, то каким будет содержимое данных. Я не знаю, как использовать эту библиотеку.   -  person user69260    schedule 19.01.2010
comment
@ Эймантас, что это значит? + или -   -  person user69260    schedule 19.01.2010
comment
@techfandu: (1) Нажмите на свое имя. (2) Нажмите на предыдущий вопрос, который вы задали. (3) Примите ответ, который помог вам больше всего. (4) Повторяйте, пока на все ваши вопросы не будет принятого ответа.   -  person Dave Jarvis    schedule 19.01.2010
comment
Вы преуспели в работе? Я должен сделать то же самое для проекта в школе (играть в odp в веб-браузере). Если бы вы могли дать мне несколько советов, это было бы здорово.   -  person Alexx    schedule 21.02.2012


Ответы (8)


Я написал распаковщик на 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
comment
Это выглядит великолепно, но я получил следующее сообщение об ошибке: Этот zip-файл использует кодировку UTF8, которая не поддерживается ZipFile.js. Какой-нибудь быстрый обходной путь, который вы можете порекомендовать? - person Giulio Prisco; 14.07.2011
comment
@Giulio - хорошо, я изменил класс ZipFile, чтобы он поддерживал декодирование имен файлов в кодировке UTF8. Это должно работать только сейчас. - person Cheeso; 07.08.2011
comment
Потрясающий! Можете ли вы добавить поддержку KMZ (Binary) и KML (XML) в JSIO.guessFileType? - person SineSwiper; 04.02.2012
comment
@Cheeso Откуда у тебя файл ZipFile.js ?? - person Sachin J; 18.06.2012
comment
@Cheeso Все ссылки js-unzip мертвы. Есть ли действующая ссылка на js-unzip? - person J punto Marcos; 20.02.2013
comment
ах да, извините. У меня есть код, нужно найти для него новый дом. Спасибо за напоминание. - person Cheeso; 20.02.2013
comment
Я бы тоже хотел увидеть ваш код. Не могли бы вы просто разместить его где-нибудь, например, на github? - person James P. Wright; 21.02.2013
comment
У меня есть старая версия одной из демонстраций онлайн, но я пришел сюда в поисках обновления. @Cheeso Были бы заинтересованы в обновленных ссылках, когда у вас будет время. - person geocodezip; 04.03.2013
comment
Вы можете получить бесплатный репозиторий SVN по адресу assembla.com и размещать его части публично (например, эти демонстрации). - person Danny Beckett; 26.05.2013
comment
@DannyBeckett - хорошо, спасибо за напоминание и предложение. Скоро выложу где-нибудь демку. - person Cheeso; 28.05.2013
comment
Теперь также есть пакет npm unzip-stream, который хорошо работает с Node.js. API потоков. - person Christian Gawron; 18.07.2019
comment
Только что получил флаг, утверждающий, что ссылки мертвы. Можете ли вы проверить это еще раз и поместить код в свой ответ SO? Вы получаете 30 000 символов. Если этого недостаточно, напишите второй ответ. От того, что эти ссылки продолжают работать, нет никакой пользы. - person Cody Gray; 31.07.2020
comment
Почему код не может быть в github вместо битых ссылок? Кажется проще. - person Peter Moore; 01.07.2021

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

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

person Dani bISHOP    schedule 17.06.2012
comment
Я использую zip.js так же, как и вы, но в сафари я получаю, что программа для чтения файлов не определена. Пожалуйста, помогите мне работать с сафари. - person user969275; 01.03.2013
comment
У меня нет опыта работы с Сафари. Вам следует обратиться к разработчикам zip.js. Внизу страницы проекта есть адрес электронной почты: gildas-lormeau.github.com/ zip.js . Возможно, это ошибка, поэтому они будут благодарны вам за уведомление. - person Dani bISHOP; 01.03.2013
comment
Спасибо за ответ, я разместил вопрос. - person user969275; 02.03.2013
comment
У меня есть файлы JSON со строкой JSON в кодировке base64 в формате zip внутри них. Мне нужен этот внутренний объект JSON. InflatorInputStream Java может распаковать его на сервере, так что на самом деле он находится в формате zip. Однако, когда я передаю декодированные данные base64 из atob() в zip.js с помощью BlobReader, я получаю сообщение об ошибке при чтении zip-файла. ошибка. Визуально вывод atob() является двоичным, поэтому BlobReader кажется правильным, все равно попробовал TextReader, он дает Формат файла не распознан. Любые идеи? - person enigment; 14.07.2018
comment
Решил мою проблему одной строкой кода с помощью pako pako.inflate(binaryData, { to: 'string' }) - person enigment; 14.07.2018

Я нашел 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.x до 3.0.0:

Метод load() и конструктор с данными (новый JSZip(data)) заменены на loadAsync().

Спасибо пользователю 2677034

person AlvaroFG    schedule 09.12.2014
comment
Это помогло мне. Спасибо. :) - person deekshith; 26.02.2016
comment
Этот метод был удален в JSZip 3.0, пожалуйста, ознакомьтесь с руководством по обновлению. - person user2677034; 17.11.2019
comment
Спасибо, чувак, это потрясающая библиотека, потому что она очень проста в использовании (по сравнению с предыдущими ответами)! - person Maxim Georgievskiy; 02.06.2020

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

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

person MySqlError    schedule 30.10.2018

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

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

ХТХ!

person codedread    schedule 11.07.2014

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

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

person OcuS    schedule 19.01.2010

Я написал класс для этого тоже. http://blog.another-d-mention.ro/programming/read-load-files-from-zip-in-javascript/ Вы можете загружать основные ресурсы, такие как javascript/css/images, непосредственно из zip-архива, используя методы класса. Надеюсь, поможет

person TheBrain    schedule 07.08.2011
comment
Я нахожу это весьма полезным! - person Florrie; 12.12.2015

Если кто-то читает изображения или другие двоичные файлы из zip-файла, размещенного на удаленном сервере, вы можете использовать следующий фрагмент для загрузки и создания zip-объекта с помощью jszip.

// this function just get the public url of zip file.
let url = await getStorageUrl(path) 
console.log('public url is', url)
//get the zip file to client
axios.get(url, { responseType: 'arraybuffer' }).then((res) => {
  console.log('zip download status ', res.status)
//load contents into jszip and create an object
  jszip.loadAsync(new Blob([res.data], { type: 'application/zip' })).then((zip) => {
    const zipObj = zip
    $.each(zip.files, function (index, zipEntry) {
    console.log('filename', zipEntry.name)
    })
  })

Теперь, используя zipObj, вы можете получить доступ к файлам и создать для них URL-адрес src.

var fname = 'myImage.jpg'
zipObj.file(fname).async('blob').then((blob) => {
var blobUrl = URL.createObjectURL(blob)
person rusty    schedule 18.11.2020