Файлы 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 может прочитать его.