Как разрешить пользователям с необходимым разрешением загружать файл через php?

У меня есть php-файл, который действует как гейткипер для всех файлов, которые я хочу, чтобы люди скачивали, у кого есть достаточные привилегии.

Код, который я использую, выдает файл пользователю

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); 

Большинство файлов довольно большие … 400 МБ-10 ГБ.

Что было бы хорошим способом сделать это, и сохранить истинные местоположения + имена файлов в секрете, так что люди не могут просто ссылаться на файлы напрямую, но HAVE связывать через мой файл download.php? File = ID gatekeeper?

благодаря

EDIT: я не спрашиваю, как выполнять аутентификацию пользователя, все, что сделано. Я просто спрашиваю, способ ли я это сделать, это хорошая идея в больших масштабах. Похоже, что это может вызвать проблемы с памятью, если я буду читать 10 ГБ файлов.

Solutions Collecting From Web of "Как разрешить пользователям с необходимым разрешением загружать файл через php?"

Хорошо, если php отправляет файлы размером около 400Mb-10Gb, это не хорошо. Вы должны каким-то образом позволить любому веб-серверу, который вы используете, фактически обслуживать файлы.

Это действительно сводится к тому, насколько безопасно вам это нужно. Самое простое решение, которое приходит на ум (но далеко не самое безопасное), использует символические ссылки с длинными случайными именами, которые ссылаются на исходный файл. Через некоторое время символические ссылки истекают и удаляются. Каждый пользователь получает свою символическую ссылку (или «токен») в файл, который они загружают. Я не уверен, как это происходит в среде 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-адрес для файла, и это «безопасность».

Вы уже это делаете – $public_filename – это то, что вы хотите назвать, частью readfile ($ file_path) является файл – это место не обнародовано. В прошлом это могло быть выше корня документа.

  1. Поместите файлы где-то, недоступные через HTTP.
  2. Создайте таблицу базы данных идентификаторов файлов с файловыми путями.
  3. Ссылка на файлы с помощью идентификатора файла (как вы отметили выше, download.php? FileID = 0000).
  4. ???
  5. Прибыль.

Как кто-то, кто делал это ранее (много лет назад), вам нужно учитывать влияние памяти, которое это будет иметь на вашем сервере. Функция readfile не была доступна тогда, поэтому возможно, вам не понадобится делать что-либо особенное для соображений памяти.

Вы захотите каким-либо образом аутентифицировать их (HTML-форму, HTTP- базовый auth , что угодно), а затем установить флаг сеанса , который может проверить ваш скрипт 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