Файлы JSZip не могут быть распакованы

Я хочу скачать несколько файлов в виде zip-файла. Когда zip-файл загружается, и я пытаюсь открыть его, я получаю следующую ошибку на macos "невозможно развернуть тест в загрузку (ошибка 1 - операция не разрешена)".

Ниже приведен код, который я использую для создания zip-файлов с использованием jszip

var pages = $pagesComponentsDownloadSavetoFileinput[0].files;
var zip = new JSZip();

for(let i = 0; i < pages.length; i++) {
    let reader = new FileReader();
    reader.onload = function() {
        zip.file(pages[i].name, pages[i].content);
        console.log(zip) // returns proper file name and content objects
    }
    reader.readAsText(pages[i]);
}

window.setTimeout(function() { // setTimeout fixes the issue
    zip.generateAsync({type:"blob"}).then(function(blob) {
    console.log(blob); // returns Blob(22) {size: 22, type: "application/zip"} with no content
    saveAs(blob, "TESTING.zip");
  }, function (err) {
    console.log(err)
  });
}, 5000);

Изменить: я использую filesaver.js, чтобы сохранить ZIP-файл

EDIT2: загруженный zip-файл имеет размер всего 22 байта и не содержит содержимого, добавленного в цикл for.

РЕДАКТИРОВАТЬ 3: регистрация "BLOB-объектов" в generateAsync не возвращает правильное содержимое. Во время регистрации zip в цикле for.

РЕДАКТИРОВАТЬ 4: я добавил setTimeout 5 секунд для zip.generateAsync, и это решило проблему. Все файлы загружаются через 5 секунд. Похоже, что zip.generateAsync срабатывает до того, как zip-файлы добавляются в цикл for. Есть ли решение, которое исправляет это, не используя ненадежный тайм-аут, возможно, запасной вариант после добавления всех файлов в цикл for?

1 ответ

reader.readAsText асинхронный: reader.onload будет называться после всего остального.

В следующем коде:

for (...) {
  reader.onload = function() {
    // 3
  };
  reader.readAsText(...); // 1
}
// 2

Вы будете зацикливаться на каждом элементе вашего массива и регистрировать обратный вызов (1), затем продолжите вне цикла (2). Наконец, когда программа чтения файлов завершает свою работу, 3 будет выполнен. Вот почему добавление setTimeout "исправить" проблему: через 5 секунд обратные вызовы закончились и заполнили zip объект.

Исправление: вы могли асинхронно читать каждый BLOB-объект и ждать завершения всех операций чтения перед вызовом. zip.generateAsync, Есть более простой способ: JSZip v3 читает BLOB-объекты, поэтому вы можете напрямую добавить их.

Редактировать:

Если предположить, pages это FileList, вы можете сделать:

for(let i = 0; i < pages.length; i++) {
    // here, pages[i] is a File (https://developer.mozilla.org/en-US/docs/Web/API/File)
    zip.file(pages[i].name, pages[i]);
}
zip.generateAsync({type:"blob"}).then(function(blob) {...});

File является специализированным Blobтак что JSZip может прочитать его.

Другие вопросы по тегам