Процесс создания Zip с Node Express для больших пакетов ZIP
Цель
Мы работаем над сайтом с небольшим объемом, где пользователи (клиент браузера) выбирают файлы изображений (284 КБ на файл), а затем запрашивают Node Express Server, чтобы связать их в ZIP для загрузки в веб-клиент.
Проблемы и ограничения дизайна
- Результирующий ZIP может быть порядка 50 МБ - 5 ГБ. Поэтому мы хотели бы дать пользователю индикатор выполнения во время создания ZIP. (Мы предполагаем, что браузер будет предоставлять текущие обновления о ходе фактической загрузки).
- Пока мы ожидаем небольшой объем запросов (1-2 запроса за раз). Однако мы не хотим полностью связывать наш 4-ядерный серверный процессор, поэтому мы хотим минимизировать синхронные вызовы, которые связывают экспресс-сервер.
- Учитывая размер ZIP, мы не можем ожидать, что он будет собран только в памяти
- Есть ли другие проблемы, о которых нам следует беспокоиться?
Вопрос
Мы предполагаем, что запуск 7zip как дочернего процесса - это плохо, так как мы не получили бы никакого запущенного статуса относительно того, сколько из 258 КБ файлов было добавлено в ZIP.
Итак, какие из следующих пакетов являются очень дружественными для Node/ExpressJS пакетами с учетом ограничений / целей дизайна, перечисленных выше?
- архиватор: https://www.npmjs.com/package/archiver
- jszip: https://www.npmjs.com/package/jszip
- easyzip: https://www.npmjs.com/package/easy-zip
- expresszip: https://www.npmjs.com/package/express-zip
- zipstream: https://www.npmjs.com/package/zip-stream
Что я вижу выше, так это то, что большинство пакетов сначала собирают файлы, а затем финализируют их в память, а затем направляют их по запросу http (вероятно, не подходит для 5 ГБ данных или я что-то упустил). Некоторые, кажется, могут использовать диск, но вопрос в том, можно ли получать события обновления при добавлении каждого файла?
Другие, кажется, полностью асинхронны, и я не вижу, как вы получите текущее значение прогресса при добавлении каждого файла в ZIP-пакет.
2 ответа
Из пакетов, перечисленных выше. Большинство не подходили
- JSZIP в основном для браузера
- EasyZip является упаковщиком узлов для JSZIP, но он не предоставляет уведомления о прогрессе при создании
- Express-Zip - это удобное решение для быстрого восстановления в памяти (но, вероятно, оно не будет соответствовать размеру ZIP, о котором мы говорим)
- ZIP-Stream является основной утилитой под Archiver. Архиватор имеет службы очередей, так что нужно просто пользовательский архиватор
- YAZL может работать, но интерфейс для отслеживания прогресса более сложен, чем Archiver
Мы выбрали Archiver, так как он имел большинство желаемых функций:
- Экспресс дружественный
- низкий объем памяти
- так же быстро, как 7ZIP для конкретных архивов изображений, которые мы создаем (нам не нужно сжимать, файлы имеют большой размер и т. д.). Возможно, производительность других типов архивов снизится на 25%
- Он не позволяет вам добавлять к существующим архивам (это была одна из функций, которую мы хотели), но adm-zip может обеспечить этот пробел
Что касается решения 7zip. Нам не нравится читать внутренности стандартного потока вывода из порожденного дочернего процесса.
- Это грязно, чтобы найти строки в потоках
- это вызывает переключение контекста для чтения потока,
- у вас есть хрупкое решение, пытающееся разобраться с тем, что производит выходной поток (например, в случае с 7zip, иногда он увеличивает счетчик на 30%, иногда на 1%), а также с другими источниками хрупких решений.
Мы предполагаем, что запуск 7zip как дочернего процесса - это плохо, так как мы не получили бы никакого запущенного статуса относительно того, сколько из 258 КБ файлов было добавлено в ZIP.
Это кажется ложным предположением.
Такая командная строка покажет прогресс для каждого файла, добавленного в архив на стандартный вывод при добавлении каждого нового файла:
7z a -bsp1 -bb3 test.7z *
Таким образом, вы можете запустить его из node.js, используя дочерний модуль процесса, и вы сможете отслеживать прогресс stdout, как это происходит. Вам нужно будет использовать spawn
не exec
так что вы можете получить stdout
данные живут так, как это происходит.
Выполнение этого в качестве дочернего процесса позволит вашему процессу nodejs свободно обслуживать другие запросы и позволит дочернему процессу управлять своей собственной памятью, независимой от nodejs.
Программа 7zip обрабатывает очень большие архивы и файлы с соответствующим использованием памяти. С правильными флагами, чтобы получить прогресс для stdout и запуск его как дочерний процесс, он, кажется, отвечает всем вашим требованиям.