Иногда при разработке сайтов можно столкнуться с задачей, когда нам нужно дать возможность скачать тот или иной файл со своего сервера, однако мы не хотим чтобы пользователи знали место его хранения, а порой вообще необходимо защититься от возможности скачать данный файл по прямой ссылке.
Я рассмотрю данную задачу в рамках второго случая, так как он ничем не отличается от первого, за исключением места хранения наших файлов.
Допустим наш сайт хранится на виртуальном хостинге в папке «/usr/myname/www/mysite.ru/» таким образом когда пользователи заходят на Ваш сайт они попадают именно в эту папку. При этом доступа «Назад» они не имеют, поэтому вполне логично для хранения файлов использовать путь, например, «/usr/myname/www/files/». Попасть в эту папку из вне (конечно если Вас не взломали) будет невозможно, поэтому можно смело скидывать туда все файлы, которые мы хотим защитить. Для большей наглядности определим, что в папке «/usr/myname/www/files/» у нас лежат файлы «1.exe», «2.exe» и т.д..
Так же определимся, что за скачивание файлов у нас будет отвечать скрипт «/usr/myname/www/mysite.ru/download.php» к которому можно обратиться «http://mysite.ru/download.php». Рассмотрим его содержимое:
<?php if(empty($_GET['file'])) die('Неверный запрос'); //проверим есть ли параметр с именем файла $file = "/usr/myname/www/files/".$_GET['file']; //полный путь к нашему файлу if(!file_exists($file)) die('Файл не найден'); //проверим существует ли файл //Заголовки ответа на запрос, что отвечаем мы потоком байт header ("Content-Type: application/octet-stream"); header ('Content-Description: File Transfer'); header ("Accept-Ranges: bytes"); header ('Content-Transfer-Encoding: binary'); header ("Content-Length: ".filesize($file)); header ("Content-Disposition: attachment; filename=".basename($file)); //Передаем наш файл в ответ на запрос readfile($file); ?>
Теперь если мы перейдем по ссылке «http://mysite.ru/download.php?file=1.exe» — мы начнем скачивать файл «1.exe» и т.д.. Собственно и все. Все достаточно просто.
Важно: данный пример несет чисто информативный характер и по больше части не явялется реализацией задачи спрятать файл. Данный пример имеет уязвимость! Если вы не догадались, то подумайте какую, если лень думать, то читайте дальше. У данного подхода не хватает проверки для переменной $_GET[‘file’]. Если передать в качестве параметра строку «../mysite.ru/[путь_к_файлу]» — это приведет к скачиванию любого файла с Вашего сайта, что может повлечь, в лучшем случае, утечку данных. Лучше вообще отказаться от передачи имени файла в качестве параметра для данной функции. Хорошим решением будет исользование переменной сессии, которая будет инициализированна заранее, или использование БД для хранения путей к файлам, и передачи в качестве параметра айди необходимой записи (так же не забываем про проверки разрешения доступа пользователю на скачивание запрашиваемого файла).