У меня есть php файл, который действует как привратник для всех файлов, которые я хочу, чтобы люди загрузили, кто ahve достаточные полномочия.
Код, который я использую, бросает файл в пользователя,
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header("Content-disposition: attachment; filename=\"".$public_filename."\"");
header("Content-Transfer-Encoding: Binary");
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header("Content-length: ".$f_filesize);
readfile($file_path);
Большинство файлов является довольно большим.... 400mb-10GB.
Каков был бы хороший способ сделать это и сохранить истинные местоположения + секрет имен файлов, таким образом, люди наклон просто связываются с файлами непосредственно, но ИМЕЮТ для соединения через мой download.php? привратник file=ID?
Спасибо
Править: Я не спрашиваю, как сделать аутентификацию пользователя, все, что сделано. Я просто спрашиваю, ли мой способ сделать его, хорошая идея в крупном масштабе. Кажется, что это могло вызвать проблемы памяти, если я продолжаю читать файлы на 10 ГБ.
Хорошо, если php отправляет файлы размером около 400 Мб-10 Гб - это не очень хорошо. Вам нужно каким-то образом позволить используемому вами веб-серверу фактически обслуживать файлы.
Это действительно сводится к тому, насколько безопасным вам нужно быть. Самое простое решение, которое приходит на ум (но далеко не самое безопасное) - это использование символических ссылок с длинными случайными именами, которые ссылаются на оригинальный файл. Через определенное время символические ссылки истекают и удаляются. Каждый пользователь получает свою символическую ссылку (или "маркер") на загружаемый файл. Я не уверен, как это работает в среде Windows, но на unix это довольно просто.
Вот некоторый псевдокод:
if($user->isAllowedToDownload($file)){
$token = md5($user->name . $file->name . time() . $someGoodRandomValue);
symlink($file, $download_path . $token);
header("Location: $download_url$token");
}
Затем вам нужно задание cron, которое очищает старые символические ссылки. Вам также нужно убедиться, что веб-сервер настроен на следование символическим ссылкам, желательно только для той папки, где создаются эти маркеры загрузки.
Таким образом, когда пользователь запрашивает domain.com/download?file=bigfile.mp4
, в публичном пространстве веб-сервера создается символическая ссылка, которая указывает на реальный файл вне публичного пространства веб-сервера. Пользователь перенаправляется на domain.com/getFile/ab739babec890103bdbca72
, что, в свою очередь, заставляет веб-сервер обслужить файл. Теперь пользователям очень трудно пытаться угадать URL-адрес файла, и в этом заключается "безопасность".
Вы захотите каким-то образом аутентифицировать их (HTML-форма, HTTP базовая аутентификация и т. Д.), А затем установить флаг session , который вы download.php скрипт может проверить. Обратите внимание, что это не мешает людям загружать файл, а затем распространять его самостоятельно.
Вы должны настроить свой веб-сервер так, чтобы реальные файлы не были доступны напрямую.
Само по себе это не вызовет проблем с памятью. readfile не читает файл в память. Однако использование PHP приведет к накладным расходам. Вы можете частично устранить эту задержку, используя X-Sendfile .
Ваш метод вызовет проблемы с памятью, однако можно читать и выводить файл кусками. Вам нужно будет использовать функцию flush() после echo
каждого куска файла. Вы также можете заставить возобновление загрузки работать с небольшим усилием. Тем не менее, такой подход требователен к процессору.
Более простым и лучшим решением является использование тега заголовка "x-sendfile", поддерживаемого как apache, так и lighttpd через их модули. Все, что вам нужно будет сделать, это просто указать имя файла в заголовке, примерно так:
header('X-Sendfile: filename-on-your-file-system');
Ссылка для lighttpd:
http://redmine.lighttpd.net/projects/lighttpd/wiki/X-LIGHTTPD-send-file
Как кто-то, кто делал это раньше (много лет назад), вы должны учитывать влияние памяти на ваш сервер. Функция readfile
тогда была недоступна, поэтому возможно, что вам не потребуется делать что-то особенное из соображений памяти.
Вы уже делаете это - $ public_filename
- это то, что вы хотите, чтобы он назывался, часть readfile ($ file_path) - это файл - ее местоположение не публикуется. После этого он мог быть выше корня документа.