Мой предыдущий ответ был частичным и не очень хорошо задокументирован, вот обновление с кратким изложением решений от него и от других участников обсуждения.
Решения упорядочены от наилучшего решения к худшему, а также от решения, требующего наибольшего контроля над веб-сервером, до решения, требующего меньшего. Кажется, не существует простого способа иметь одно решение, которое было бы быстрым и работало повсюду.
Использование заголовка X-SendFile
Как задокументировано другими, это на самом деле лучший способ. Основой является то, что вы делаете свой контроль доступа в php, а затем вместо того, чтобы отправлять файл самостоятельно, вы говорите веб-серверу сделать это.
Основной код php:
header("X-Sendfile: $file_name");
header("Content-type: application/octet-stream");
header('Content-Disposition: attachment; filename="' . basename($file_name) . '"');
Где $file_name
- полный путь в файловой системе.
Основная проблема этого решения заключается в том, что он должен быть разрешен веб-сервером и либо не установлен по умолчанию (apache), либо не активен по умолчанию (lighttpd), либо требует специальной конфигурации (nginx).
Apache
В apache, если вы используете mod_php, вам нужно установить модуль с именем mod_xsendfile , а затем настроить его (либо в конфигурации apache, либо в .htaccess, если вы это разрешите)
XSendFile on
XSendFilePath /home/www/example.com/htdocs/files/
С этим модулем путь к файлу может быть либо абсолютным, либо относительно указанного XSendFilePath
.
Lighttpd
Mod_fastcgi поддерживает это при настройке с
"allow-x-send-file" => "enable"
Документация для этой функции есть в lighttpd wiki , они документируют заголовок X-LIGHTTPD-send-file
, но имя X-Sendfile
также работает
Nginx
В Nginx вы не можете использовать заголовок X-Sendfile
, вы должны использовать собственный заголовок с именем X-Accel-Redirect
. Он включен по умолчанию, и единственное реальное отличие состоит в том, что его аргумент должен быть URI, а не файловой системой. Следствием этого является то, что вы должны определить местоположение, помеченное как внутреннее в вашей конфигурации, чтобы клиенты не находили реальный URL файла и не переходили непосредственно к нему, их вики содержит хорошее объяснение этого.
Символические ссылки и заголовок Location
Вы можете использовать символические ссылки и перенаправлять на них, просто создавая символические ссылки на ваш файл со случайными именами, когда пользователь авторизован для доступа к файлу и перенаправить пользователя на него, используя:
header("Location: " . $url_of_symlink);
Очевидно, вам понадобится способ обрезать их либо при вызове скрипта для их создания, либо через cron (на компьютере, если у вас есть доступ, либо через какой-либо сервис webcron в противном случае)
В apache необходимо включить FollowSymLinks
в .htaccess
или в конфигурации apache.
Контроль доступа по IP и заголовку местоположения
Еще один хак - генерировать файлы доступа Apache из php, разрешая явный IP-адрес пользователя. Под apache это означает использование mod_authz_host
(mod_access
) Allow from
команд.
Проблема в том, что блокировка доступа к файлу (так как несколько пользователей могут захотеть сделать это одновременно) не тривиальна и может привести к тому, что некоторые пользователи будут ждать долго. И все равно вам все равно нужно удалить файл.
Очевидно, что другая проблема может заключаться в том, что несколько человек за одним и тем же IP могут получить доступ к файлу.
Когда все остальное терпит неудачу
Если у вас действительно нет способа заставить ваш веб-сервер помочь вам, единственное оставшееся решение - это readfile , оно доступно во всех используемых в настоящее время версиях php и работает довольно хорошо (но не т действительно эффективный).
Комбинированные решения
В общем, лучший способ действительно быстро отправить файл, если вы хотите, чтобы ваш php-код использовался везде, - это иметь где-то настраиваемую опцию с инструкциями по ее активации в зависимости от веб-сервера и, возможно, автоопределением. в вашем скрипте установки.
Это очень похоже на то, что делается во многих программах для
- Чистые URL (
mod_rewrite
на apache)
- Крипто-функции (
mcrypt
php модуль)
- Поддержка многобайтовой строки (
mbstring
модуль php)