Розпакування файлів


79

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

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

Як я можу це зробити?


7
"без успіху", будь ласка, будьте конкретнішими, покажіть нам якийсь код, покажіть нам деякі помилки ... ми тут, щоб допомогти, а не вгадати.
OcuS

В основному я щойно викликав функцію роздування - data = zip_inflate (src); Але я думаю, що це призначено для одного файлу. Якщо zip-файли містять кілька файлів у структурі каталогів, то яким буде вміст "даних". Я не знаю, як користуватися цією бібліотекою.
user69260

@Eimantas що це означає? + Або -
user69260

4
@techfandu: (1) Клацніть на своє ім'я. (2) Клацніть на попереднє запитання, яке ви задавали. (3) Прийміть відповідь, яка вам найбільше допомогла. (4) Повторюйте, поки на всі ваші запитання не буде прийнято відповіді.
Dave Jarvis

Ви досягли успіху в роботі? Я повинен зробити те ж саме для проекту в школі (відтворити odp у веб-браузері) .. Якби ви могли дати мені деякі вказівки, це було б неймовірно.
Alexx,

Відповіді:


61

Я написав розпаковку в Javascript. Це працює.

Він покладається на зчитувач двійкових файлів Andy GP Na та деякі 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, один для класу надування та інший для класу зчитування двійкових файлів. Демо-версія також залежить від 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));
    }
}

Демонстрація працює в кілька кроків: readFilefn запускається клацанням і створює екземпляр об’єкта ZipFile, який зчитує zip-файл. Існує асинхронний зворотний виклик, коли зчитування завершується (зазвичай це відбувається менш ніж за секунду для стиснутих ZIP-кодів розумного розміру) - у цій демонстрації зворотний виклик утримується в локальній змінній doneReading, яка просто викликає extractEntries, яка просто наосліп розпаковує весь вміст наданого zip-файл. У реальному додатку ви, мабуть, вибрали б деякі записи, які потрібно витягти (дозволити користувачеві вибрати, або вибрати один або декілька записів програмно тощо).

У extractEntriesFn перебирає всі записи, і виклики extract()на кожному з них, проходячи зворотний виклик. Декомпресія запису вимагає часу, може бути 1s або більше для кожного запису в zip-файлі, що означає, що асинхронність є доречною. Витяг зворотного виклику просто додає витягнутий вміст до акордеону jQuery на сторінці. Якщо вміст є двійковим, то він відформатовується як такий (не показано).


Це працює, але я думаю, що корисність дещо обмежена.

Одне: це дуже повільно. Розпакування файлу 140k AppNote.txt із PKWare займає ~ 4 секунди. Те саме розпакування можна зробити менш ніж за .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, оскільки вона призначена для підтримки> 4gb zip-файлів - не потрібно витягувати їх у браузері.

Я також не перевіряв справу на розпакування двійкового вмісту. Зараз він розпаковує текст. Якщо у вас є заархівований двійковий файл, вам потрібно буде відредагувати клас ZipFile, щоб правильно його обробляти. Я не зрозумів, як це робити чисто. Зараз він також робить двійкові файли.


РЕДАКТУВАТИ - Я оновив бібліотеку та демонстраційну версію JS. Тепер він робить бінарні файли, крім тексту. Я зробив його більш еластичним та загальним - тепер ви можете вказати кодування, яке використовуватиметься при читанні текстових файлів. Також демонстрація розширена - серед іншого вона показує розпакування файлу XLSX у браузері.

Отже, хоча я думаю, що це обмежено корисно та цікаво, це працює. Я думаю, це працювало б у Node.js.


Це виглядає чудово, але я отримав таке повідомлення про помилку: Цей zip-файл використовує UTF8, який не підтримується ZipFile.js. Будь-який швидкий обхідний шлях, який ви можете порадити?
Джуліо Пріско

@Giulio - добре, я змінив клас ZipFile для підтримки декодування імен файлів, закодованих UTF8. Це має просто працювати зараз.
Cheeso

Чудово! Чи можете ви додати підтримку KMZ (двійковий) та KML (XML) до JSIO.guessFileType?
Brendan Byrd

1
У мене є стара версія однієї з демонстраційних версій в Інтернеті , але я прийшов сюди шукати оновлення. @Cheeso Буде зацікавлений в оновлених посиланнях, коли у вас буде час.
геокодезіп 04.03.13

1
@DannyBeckett - добре, дякую за нагадування та пропозицію. Незабаром я десь викладу демо.
Cheeso

26

Я використовую zip.js, і це видається дуже корисним. Варто подивитися!

Наприклад, перевірте демонстрацію розпакування .


я використовую zip.js те саме, що і ви, але в сафарі я отримую програму читання файлів не визначено. pls допоможе мені працювати з сафарі.
user969275 01.03.13

У мене немає досвіду роботи з Safari. Вам слід звернутися до розробників zip.js. Внизу сторінки проекту є електронна адреса: gildas-lormeau.github.com/zip.js . Можливо, це помилка, тому вони подякують вам за повідомлення.
Дани Єпископ

Дякуємо за відповідь, я опублікував проблему.
user969275 02.03.13

У мене є файли JSON з кодованим рядком JSON base64 у форматі zip. Мені потрібен внутрішній об'єкт JSON. InflatorInputStream Java може розпакувати його на сервері, тому насправді він знаходиться у форматі zip. Однак, коли я передаю декодовані дані base64 з atob () до zip.js за допомогою BlobReader, я отримую "Помилка під час читання zip-файлу". помилка. Візуально вихід з atob () є двійковим, тому BlobReader здається правильним, спробував TextReader у будь-якому випадку, він дає "Формат файлу не розпізнається." Будь-які ідеї?
загадка

Зіграло свою проблему в одному рядку коду з PAKO pako.inflate(binaryData, { to: 'string' })
enigment

17

Я знайшов 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 (дані)) замінено loadAsync ().

Дякую користувачеві 2677034


1
Це мені допомогло. Дякую. :)
deekshith

1
Цей метод було вилучено в JSZip 3.0, перегляньте посібник з оновлення.
user2677034

1
Дякую, чудова бібліотека, адже вона надзвичайно проста у використанні (порівняно з попередніми відповідями)!
Максим Георгієвський

5

Якщо вам потрібна підтримка інших форматів або просто вам потрібна хороша продуктивність, ви можете скористатися цією бібліотекою WebAssembly

це обіцяно, він використовує WebWorkers для створення потоків, а API насправді є простим модулем ES


3

Я написав "Бінарні інструменти для JavaScript", проект з відкритим кодом, що включає можливість розпаковувати, розпаковувати та розпаковувати: https://github.com/codedread/bitjs

Використовується в моєму читачі коміксів: https://github.com/codedread/kthoom (також з відкритим кодом).

HTH!


2

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

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



0

Якщо хтось читає зображення або інші двійкові файли з 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)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.