Контролируемые скачивания в 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 можно обозвать так-же как и папку с файлами
location /download_files { add_header Content-type application/octet-stream; internal; }извне туда уже не попадешь
в конце концов:
location /download_files { allow 127.0.0.1; deny all; }Тут приведен лишь общий принцип
Супер!!! Спасибо за статью!
А то сейчас раздаю из самого приложения, что создает неимоверную нагрузку.
А насчет некрасивого имени, лучше не стоит, как говорят - что знает один то знает и морская свинка.
пс, понтовая капча :)
спасибо :)
Отправить комментарий