Контролируемые скачивания в Nginx
Контролируемое скачивание, реализуемое в веб сервере Nginx с использованием заголовка X-Accel-Redirect, подразумевает следующий алгоритм при отдаче контента:
- Клиент нажимает на ссылку "скачать файл"
- Запрос передается веб серверу Nginx
- Nginx в свою очередь передает запрос некоему скрипту на проверку
- Скрипт, после проверки, например валидности запроса на скачивание, возвращает запрос в Nginx, устанавливая заголовок X-Accel-Redirect
- Запрос с заголовком X-Accel-Redirect попадает в специальный внутренний location, сервера Nginx, откуда и отдается клиенту
Итак, в данном примере, используются: операционная система FreeBSD 7.1-STABLE amd64, веб сервер Nginx версии 0.7.64 (последний релиз из стабильной ветки на момент написания данного материала). В качестве бакэнда будем использовать PHP в режиме FastCGI сервера, запущенный с помощью утилиты spawn_fcgi.
Корень сайта у нас будет расположен в /home/test/public_html, файлы для скачивания /home/test/public_html/download_files. Для примера набросаем примитивный скрипт down.php и положим в корень сайта а в папку download_files, положим какой-нибудь файл для скачивания, например архив test.zip
<?php
$path= $_GET['file_name'];
// принимаем имя файла
..............
// делаем какую-то проверку или обработку
..............
header("X-Accel-Redirect: /internal_files/" . $path);
// возвращаем запрос с установленным заголовком X-Accel-Redirect
?>
Конфигурация Nginx у нас, будет выглядеть следующим образом:
server { listen 192.168.50.20:80; server_name nginx.grt; error_log logs/nginx_error.log error; root /usr/home/test/public_html; location / { index index.php index.html index.htm; } location /downloads/ { rewrite ^/downloads/(.*) /down.php?file_name=$1 break; fastcgi_pass unix:/tmp/fastcgi_socket; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } location /internal_files { alias /home/test/public_html/download_files; add_header Content-type application/octet-stream; internal; } location ~ \.php$ { fastcgi_intercept_errors off; fastcgi_pass unix:/tmp/fastcgi_socket; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; }
Теперь что происходит при запросе http://nginx.grt/downloads/test.zip. Первоначально, запрос клиента попадает в location /downloads/, здесь, URI-часть запроса переписывается с помощью модуля ngx_http_rewrite_module, принимает вид, /down.php?file_name=test.zip и отправляется на выполнение, на FastCGI сервер. Скрипт, приняв в качестве параметра, путь к файлу, производит какие-то манипуляции и возвращает в Nginx запрос, в виде /internal_files/test.zip, с установленным заголовком X-Accel-Redirect, который в свою очередь будет обработан в location /internal_files.
В location /internal_files, прописана директива alias, указывающая путь на диске, до папки с файлами и заменяющая собой соответствующий location, и ключевое слово, Internal, говорящее, что данный location, обрабатывает только внутренние запросы сервера Nginx и запросы X-Accel-Redirect, то есть внешние запросы в этот location не попадут. В итоге всех этих манипуляций, с диска будет отдан файл /home/test/public_html/download_files/test.zip.
Вот собственно и все.
Комментарии
А если сделать запрос site.ru/download_files/test.zip то файл отдаётся. Проверьте.
Ну папка с файлами может называться например Hb1u1G7S9ghUr$59gks_a6F6khg4DJs58vb
Кроме того, внутренний location можно обозвать так-же как и папку с файлами
извне туда уже не попадешь
в конце концов:
Тут приведен лишь общий принцип
Супер!!! Спасибо за статью!
А то сейчас раздаю из самого приложения, что создает неимоверную нагрузку.
А насчет некрасивого имени, лучше не стоит, как говорят - что знает один то знает и морская свинка.
пс, понтовая капча :)
спасибо :)
Отправить комментарий