Работа с ZIP-архивами в TypeScript: библиотека JSZip и утилиты

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Работа с ZIP-архивами в TypeScript: библиотека JSZip и практические примеры

В современной веб-разработке часто возникает необходимость упаковывать несколько файлов в один архив для удобной загрузки или передачи данных. В экосистеме TypeScript (и JavaScript) наиболее популярным решением для работы с ZIP-архивами является библиотека JSZip. Она позволяет создавать, читать и модифицировать ZIP-файлы как в браузере, так и в среде Node.js.

В этой статье мы подробно разберём установку, настройку и основные сценарии использования JSZip в TypeScript-проектах. Вы научитесь создавать архивы из строк, бинарных данных и целых папок, а также извлекать содержимое существующих ZIP-файлов.

Установка и подключение JSZip

Для начала работы установите библиотеку и её типы через npm или yarn:

npm install jszip
npm install --save-dev @types/jszip

После установки импортируйте JSZip в ваш TypeScript-файл:

import JSZip from 'jszip';

Если вы используете модульную систему (ES modules), импорт будет работать как показано выше. Для CommonJS (require) синтаксис может отличаться, но в TypeScript-проектах рекомендуется использовать ES-импорты.

Создание нового ZIP-архива

Самый простой сценарий — создать архив и добавить в него несколько текстовых файлов. Рассмотрим пример:

const zip = new JSZip();

// Добавляем текстовые файлы
zip.file("hello.txt", "Hello, World!");
zip.file("readme.md", "# Документация\n\nЭто пример Markdown-файла.");

// Добавляем папку и файл внутри неё
const folder = zip.folder("images");
folder.file("logo.png", "base64encodedstring...", {base64: true});

// Генерируем ZIP-файл как Blob
zip.generateAsync({type: "blob"}).then((content) => {
    // Создаём ссылку для скачивания
    const link = document.createElement("a");
    link.href = URL.createObjectURL(content);
    link.download = "my-archive.zip";
    link.click();
});

В этом примере мы:

  • Создали экземпляр JSZip
  • Добавили два текстовых файла методом .file()
  • Создали вложенную папку images и поместили в неё файл с base64-данными
  • Сгенерировали архив в формате Blob и инициировали скачивание

Чтение и извлечение существующего ZIP-архива

JSZip позволяет не только создавать, но и читать архивы. Для этого используется метод loadAsync():

async function readZipFile(zipBlob: Blob): Promise<void> {
    try {
        const zip = await JSZip.loadAsync(zipBlob);
        
        // Получаем список всех файлов
        const fileNames = Object.keys(zip.files);
        console.log("Файлы в архиве:", fileNames);

        // Извлекаем содержимое конкретного файла
        const helloFile = zip.file("hello.txt");
        if (helloFile) {
            const content = await helloFile.async("string");
            console.log("Содержимое hello.txt:", content);
        }

        // Итерация по всем файлам
        zip.forEach((relativePath, zipEntry) => {
            console.log(`Найден файл: ${relativePath}, размер: ${zipEntry._data.uncompressedSize} байт`);
        });

    } catch (error) {
        console.error("Ошибка при чтении ZIP:", error);
    }
}

Обратите внимание на типизацию: JSZip.loadAsync() возвращает промис, который разрешается в объект JSZip. Метод .file() возвращает JSZipObject | null, поэтому перед вызовом .async() нужно проверить существование файла.

Работа с бинарными данными и изображениями

Часто требуется упаковать в архив изображения или другие бинарные файлы. JSZip поддерживает работу с ArrayBuffer, Blob, Uint8Array и base64:

// Добавление файла из ArrayBuffer
const buffer = new ArrayBuffer(8);
const view = new Uint8Array(buffer);
view.set([0x48, 0x65, 0x6C, 0x6C, 0x6F]); // "Hello" в UTF-8
zip.file("binary.dat", buffer);

// Добавление файла из Blob (например, с сервера)
const response = await fetch("https://example.com/image.png");
const imageBlob = await response.blob();
zip.file("photo.png", imageBlob);

// Чтение файла как ArrayBuffer
const file = zip.file("photo.png");
if (file) {
    const arrayBuffer = await file.async("arraybuffer");
    console.log("Размер изображения:", arrayBuffer.byteLength);
}

Опции сжатия и настрой

Рекомендаций