Привет, я хочу, чтобы пользователь мог загружать PDF-файл с моего сервера (Windows), настроенного с помощью nginx PHP. Это мой nginx.conf (серверный блок)
http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; server { listen 80; server_name localhost; location / { root html; index index.php; } location /download { internal; alias /protected; } } }
.. и файл PHP (часть заголовка)
$file = '/download/real-pdf-file.pdf'; //this is the physical file path $filename = 'user-pdf-file.pdf'; //this is the file name user will get header('Cache-Control: public, must-revalidate'); header('Pragma: no-cache'); header('Content-Type: application\pdf'); header('Content-Length: ' .(string)(filesize($file)) ); header('Content-Disposition: attachment; filename='.$filename.''); header('Content-Transfer-Encoding: binary'); header('X-Accel-Redirect: '. $file);
Файл – это вызов из URL-адреса, например:
download.php?id=a2a9ca5bd4a84294b421fdd9ef5e438ded7fcb09
Я попробовал несколько примеров / решений отсюда, но пока никто не работает. Файл большой (от 250 до 400 МБ каждый), и каждый пользователь сможет загрузить 4 файла.
Нет проблем с загрузкой части с использованием PHP, только конфигурация nginx, которая кажется неработающей. Не обнаружен журнал ошибок.
Хорошо, здесь есть пара вопросов:
1) Плутинговый корень внутри местоположения – BAD IDEA в соответствии с разработчиками nginx.
2) Внутренний URL-адрес, используемый для указания Nginx, что это внутренняя переадресация, не должен подвергаться воздействию пользователей.
3) Я не могу видеть, где находится ваш файл download.php, поэтому я изменил ваш блок корневого местоположения, чтобы использовать try_files, поэтому запрос /download.php будет обслуживаться этим файлом, а не index.php.
Ваш проект должен быть выложен как:
project\ html - this is the root of your website protected - this directory is not accessible directly
И ваш Nginx conf должен выглядеть так:
http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; server { listen 80; server_name localhost; root /path/to/project/html; location / { try_files $uri /index.php?$args; } location /protected_files { internal; alias /path/to/project/protected; } } }
Это хорошая идея не повторять использование одних и тех же имен, чтобы иметь в виду разные вещи, поскольку это довольно запутанно. Я изменил их, так что теперь protected
относится только к фактическому физическому каталогу, в котором хранятся файлы, которые вы хотите обслуживать. protected_files
– это просто строка, которая позволяет Nginx соответствовать запросу из заголовка x-accel.
Единственное, что нужно изменить в вашем PHP-коде, – это использовать правильную строку, чтобы Nginx мог забрать внутреннее местоположение:
$aliasedFile = '/download/real-pdf-file.pdf'; //this is the nginx alias of the file path $realFile = '/path/to/project/protected/real-pdf-file.pdf'; //this is the physical file path $filename = 'user-pdf-file.pdf'; //this is the file name user will get header('Cache-Control: public, must-revalidate'); header('Pragma: no-cache'); header('Content-Type: application\pdf'); header('Content-Length: ' .(string)(filesize($realFile)) ); header('Content-Disposition: attachment; filename='.$filename.''); header('Content-Transfer-Encoding: binary'); header('X-Accel-Redirect: '. $aliasedFile); exit(0);
Основываясь на рекомендации и решении от Danak и некоторых разъяснениях от Carsten, я обнаружил, что в Windows Serve нам нужно установить полный путь в псевдониме следующим образом:
location /protected_files { internal; alias C:/absolute/path/to/project/protected/; }
Обратите внимание, что необходима дополнительная косая черта (в моем случае, Windows 7 Pro для разработки, Windows Server 2008 для развертывания). Единственная проблема – теперь мне нужно протестировать одновременные загрузки, чтобы убедиться, что ресурсы сервера запущены.
Я новичок в nginx, поскольку мне кажется, что я быстрее переключаюсь с Apache. Спасибо парню за просветление! Я рад быть частью сообщества Stackoverflow 🙂