Часто веб-службе необходимо закрепить несколько больших файлов для загрузки клиентом. Самый очевидный способ сделать это - создать временный 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?