Подавать большой файл с PHP и nginx X-Accel-Redirect

Привет, я хочу, чтобы пользователь мог загружать 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 🙂