DevGang
Авторизоваться

Рекурсивное извлечение Zip-файлов с помощью NodeJS 

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

Решение проблемы

  1. Найти библиотеку для распаковки
  2. Распакуйте основной zip-файл, т.е. demo.zip.
  3. Найдите способ рекурсивного обхода всей структуры папок
  4. Затем извлекайте файл .zip всякий раз, когда он будет найден.

Решение

Библиотека extract-zip, используется для извлечения файлов zip.

Метод извлечения zip-файла

  1. Он принимает два входных аргумента: источник и цель. source должен быть абсолютным путем к zip-файлу, target - куда будет извлечена папка.
async function extractZip(source, target) {
  try {
    await extract(source, { dir: target });
    console.log("Extraction complete");
  } catch (err) {
    console.log("Oops: extractZip failed", err);
  }
}

Метод рекурсивного обхода папок

const unzipFiles = async function (dirPath) {
  const files = fs.readdirSync(dirPath);

  await Promise.all(
    files.map(async (file) => {
      if (fs.statSync(dirPath + "/" + file).isDirectory()) {
        await unzipFiles(dirPath + "/" + file);
      } else {
        const fullFilePath = path.join(dirPath, "/", file);
        const folderName = file.replace(".zip", "");
        if (file.endsWith(".zip")) {
          zippedFiles.push(folderName);
          await extractZip(fullFilePath, path.join(dirPath, "/", folderName));
          await unzipFiles(path.join(dirPath, "/", folderName));
        }
      }
    })
  );
};

Много действий в приведенном выше фрагменте. Расшифруем

  1. dirPath: путь извлечения файла
  2. Метод fs.readdirSync() используется для синхронного чтения содержимого данного каталога. Метод возвращает массив со всеми именами файлов или объектов в каталоге.
  3. Теперь основная задача заключалается в том, чтобы асинхронно перебрать все папки / файлы. Мы не можем использовать forEach, так как он не поддерживает ключевое слово async/await. Традиционный синтаксис цикла for работает с ключевым словом await. Но я хотел использовать более распространенный метод массива map().
  4. Если вы используете await с map (), он возвращает массив обещаний. Следовательно, для разрешения всех обещаний здесь используется Promise.all(arrayOfPromises).
if (fs.statSync(dirPath + "/" + file).isDirectory()) {
        await unzipFiles(dirPath + "/" + file);
      }

Чтобы проверить, является ли текущий объект файлом или папкой, используется метод isDirectory (). Если это папка, то снова вызовите тот же метод, т. е. i.e unzipFiles()

else {
        const fullFilePath = path.join(dirPath, "/", file);
        const folderName = file.replace(".zip", "");
        if (file.endsWith(".zip")) {
          zippedFiles.push(folderName);
          await extractZip(fullFilePath, path.join(dirPath, "/", folderName));
          await unzipFiles(path.join(dirPath, "/", folderName));
        }
  1. Если файл найден, мы вызовем метод extractZip() с sourceи target с их абсолютными путями.
  2. Если мы не укажем target или дадим ему текущий путь, он сам распакует все файлы в текущем каталоге. Но я хотел распаковать zip в соответствующие имена папок.
  3. Чтобы добиться этого, я склеил имя папки из файла .zip, передав его в качестве target для метода extractZip().Теперь в последней строке есть еще одна загвоздка, т.е.
await unzipFiles(path.join(dirPath, "/", folderName));
  1. Поскольку существует вероятность того, что извлеченные файлы также могут содержать внутри себя zip-файлы, поэтому, как только мы извлечем какой-либо файл, нам снова придется вызывать unzipFiles() для просмотра извлеченных файлов.

Выход будет 

Большое спасибо за чтение 🙏

Источник:

#JavaScript #NodeJS
Комментарии
Чтобы оставить комментарий, необходимо авторизоваться

Присоединяйся в тусовку

Поделитесь своим опытом, расскажите о новом инструменте, библиотеке или фреймворке. Для этого не обязательно становится постоянным автором.

Попробовать

В подарок 100$ на счет при регистрации

Получить