Nginx

индекс
267,67

Редкие фичи nginx: mod_zip

Раз уж зашел разговор о редких и полезных модулях для nginx — я расскажу вам об онлайн упаковщике ZIP файлов для nginx. Он позволяет на лету формировать ZIP архив из заданного списка файлов с возможностью многопоточной скачки и докачки файла, но без сжатия.


Пример использования


Есть большой сервис для хранения пользовательских файлов. Одной из фич нашего файлшаринга является то, что можно залить торрент файл, а наша система его уже сама скачает и закачает на сервера. Очень часто, скаченные торренты бывают разбиты на десятки файлов по 10-100 Мбайт и чтобы скачать их все — пользователю придется кликнуть от 10 до 100 раз на каждый файл, чтобы скачать архив целеком. Но с помощью nginx mod_zip мы позволяем пользователю кликнуть всего один раз и просто наслаждаться скоростью скачки ;) (те люди, которые скажут что проще систему научить самой разархивировать такие файлы — пусть почитают про Zip Bomb)

Плюсы


1. Экономия места и процессорного времени на создание статичного ZIP файла.
2. Скачивание такого ZIP файла не занимает больше ресурсов, чем скачивание одного статического файла с nginx

Минусы


1. Необходимо знать точный размер, путь и crc32 файла. (Если не указать crc32 — не будет поддерживаться докачка и многопоточность)
2. Версия 1.1.4 не поддерживает суммарный вес архива больше 4 GB. Код который это исправляет уже был послан автору плагина на ревью. За патчик огромное спасибо хабраюзеру vasfed. Этот код скоро будет включен в основную ветку.
3. Есть подтвержденный баг с многопоточной скачкой, который обещали поправить в версии 1.1.5 (в некоторых случаях файл скачивается битым)

Как начать использовать?


1. Скачать mod_zip 1.1.4 и перекомпилировать nginx с ключиком --add-module=/path/to/mod_zip-1.x
2. В Вашем скрипте передать заголовок: «X-Archive-Files: zip» (так mod_zip поймет что ему пора приниматься за работу)
3. Вывести список необходимых файлов вида:

1034ab38 428 /foo.txt My Document1.txt
83e8110b 100339 /bar.txt My Other Document1.txt

4. Скачать ZIP файл и наслаждаться.

Пройденные грабли


1. Если хоть один из переданных Вами файлов отсутствует на диске — весь архив скачается битым, поэтому надо проверять наличие файлов по факту запроса ZIP файла.
2. Если вы неправильно передали размер файла — архив скачается битым.
3. Разные утилиты генерируют разные значения crc32. Мы остановились на пакете «perl-Archive-Zip» (Fedora), который включает в себя утилитку crc32, написанную на перле.

p.s. о выходах новыйх версий mod_zip — я буду сообщать в рассылку nginx
+6
27 августа 2009, 22:11
6

комментарии (15)

0
soltpain #
Самый большой недостаток в формате списка, который передается на обработку — разделители пробелы, хотя можно было использовать табуляции, нельзя например передать
1034ab38 428 /foo bar.txt My Document1.txt

Приходится париться через подзапрос к бакенду
1034ab38 428 /file.php=123 My Document1.txt

который через X-Accel-Redirect отдаст уже /foo bar.txt

PS: для корректной обработки внутренних подзапросов нужно передавать в FCGI следующее:
fastcgi_param REQUEST_URI $uri$is_args$query_string
0
soltpain #
PPS: в пхп нужное значение crc32 можно вычислить через hash_file('crc32b', $PathToFile); — достаточно долгая вещь, на 10-15 файлов, размером 60-100Мб (типичный альбом в mp3) уходит несколько секунд.

И если не считать эти суммы, а передавать вместо них символ -, архив сгенерируется, но WinRar будет ругаться что архив поврежден, но легко лечится встроенной функцией Repair (CTRL+R)
0
Mastyf #
У меня лично crc таким способом считалось неправильно.
0
soltpain #
Я просто перебирал все методы crc в пхп пока не получил нужное значение, которое указано в тестовых файлах модуля
0
crocodile2u #
Ну, значение crc32 можно посчитать единожды — и потом хранить его, уже посчитанное — в БД или, скажем, рядом с файлом складывать файл <filename>.crc32.txt. Таким образом — главное, чтобы crc32 считался ровно так же, как это делает nginx.
0
vasfed #
Третье поле — не имя файла, а URL (вообще говоря, может быть и не локальным), в нем не может быть пробелов в явном виде (см. RFC1738), если нужны — смело меняйте на %20.
0
soltpain #
Да и нас не пальцем делали, пробовал в первую очередь URLEncoded значения подставлять, но в подзапрос они уходят нераскодироваными (в логах записи типа этой: file /foo%20bar.txt not found). Я уже и Евану Миллеру про эту проблему где-то с год назад написал, он согласился, что это возможно баг, но с апдейтами не торопится.
Так что на текущий момент, третий параметр это всё-таки имя файла, относительно documet_root конечно.
0
vasfed #
Действительно бага, nginx в подзапросе хочет уже распарсенный uri, причем локальный
Пофикшу, как время будет — приоритет невысокий
0
vasfed #
Отправил патч для поддержки url-encoded подзапросов Эвану, ждем включения в оф. ветку.
0
soltpain #
большое спасибо, бум ждать новую версию!
0
vasfed #
Можете собирать из svn revision 12 ;)
0
ixside #
Можно поинтересоваться что у вас за файлшаринг?
0
zxmd #
А что Zip Bomb до сих пор используют? Помнится во времена фидо часто прилетали такие вот «трояны».
0
david_mz #
Zip Bomb тут, вроде бы не при чём — речь ведь идёт не о приёме, а об отдаче архива.
0
vasfed #
Патч для поддержки ZIP64 внесен в svn r11 и войдет в следующий релиз.

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.