Часто веб-службе необходимо закрепить несколько больших файлов для загрузки клиентом. Самый очевидный способ сделать это - создать временный zip файл, затем либо echo для пользователя, либо сохранить его на диск и перенаправить (удалив его в будущем).
Однако, делать то, что имеет недостатки:
- начальная фаза интенсивного процессора и разгона диска, в результате чего...
- значительная начальная задержка для пользователя при подготовке архива.
- очень большой объем памяти для каждого запроса
- использование значительного временного дискового пространства
- если пользователь отменяет загрузку на полпути, все ресурсы, используемые в начальной фазе (процессор, память, диск), будут потрачены впустую.
Решения, такие как ZipStream-PHP, улучшают это путем перетаскивания данных в файл Apache по файлу. Тем не менее, результат по-прежнему характеризуется высоким использованием памяти (файлы полностью загружаются в память) и большими мощными всплесками на диске и использовании ЦП.
В отличие от этого, рассмотрите следующий bash фрагмент:
ls -1 | zip [email protected] - | cat > file.zip
# Note [email protected] is not supported on MacOS
Здесь zip работает в потоковом режиме, что приводит к низкому объему памяти. Труба имеет встроенный буфер - когда буфер заполнен, ОС приостанавливает программу записи (программа слева от трубы). Это гарантирует, что zip работает только так быстро, как его вывод может быть записан cat.
Оптимальным способом было бы сделать то же самое: замените cat на процесс веб-сервера, потоковой передачи zip файла пользователю, создав его на лету. Это создавало бы небольшие накладные расходы по сравнению с просто потоковой передачей файлов и имело бы непродуманный, не прокручиваемый профиль ресурсов.
Как вы можете добиться этого в стеке LAMP?