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

У меня есть 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 ГБ.

6
задан 9 June 2010 в 22:37
поделиться

5 ответов

Хорошо, если 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-адрес файла, и в этом заключается "безопасность".

10
ответ дан 8 December 2019 в 15:59
поделиться

Вы захотите каким-то образом аутентифицировать их (HTML-форма, HTTP базовая аутентификация и т. Д.), А затем установить флаг session , который вы download.php скрипт может проверить. Обратите внимание, что это не мешает людям загружать файл, а затем распространять его самостоятельно.

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

Само по себе это не вызовет проблем с памятью. readfile не читает файл в память. Однако использование PHP приведет к накладным расходам. Вы можете частично устранить эту задержку, используя X-Sendfile .

1
ответ дан 8 December 2019 в 15:59
поделиться

Ваш метод вызовет проблемы с памятью, однако можно читать и выводить файл кусками. Вам нужно будет использовать функцию 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

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

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

1
ответ дан 8 December 2019 в 15:59
поделиться

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

2
ответ дан 8 December 2019 в 15:59
поделиться
Другие вопросы по тегам:

Похожие вопросы: