Меня уже давно интересовал вопрос, как например, при клике по ссылке вида: http://servicefile/files/d58y1e предлагается скачать файл к примеру с названием test.zip. По такому принципу работают файлообменники. Оказалось все достаточно просто. Сейчас я сделаю небольшое отступление.
Во времена статических web сайтов, у вебмастеров были весьма сильно связаны руки, не было возможности для реализации многих идей. Да и сайты кроме набора текста и пару картинок с баннерами, больше ничего из себя не представляли. Но времена изменились. И сейчас встретить в сети статический сайт становиться постепенно так же сложно, как раньше можно было бы встретить в сети сайт динамический. Но с появлением таких языков для веб программирования как PHP, ASP.NET и других, интернет в большой степени словно “обогатился”. Соответственно появилось очень большое количество технических возможностей по созданию веб сайтов. Раньше все в больше мере ограничивалось HTML в связке с JavaScript и редко с VBScript. Появились интернет магазины, электронные библиотеки, файлообменники, информационные порталы и другие, интересные и полезные веб ресурсы. Нет, конечно, они и раньше существовали, но это были не те магазины и порталы. И вот у владельце таких ресурсов возникла задача, а как сделать так, чтобы при выдаче ссылки на загрузку того или иного файла, не выдать реальное его местоположение. К примеру, файл, ссылка на который была представлена выше, физически находиться на servicefile/www/files/ и имеет имя test.zip. Как же так? Наверняка спросите вы, а все гениально просто. Есть такой очень и очень хороший модуль mod_rewrite который включается в стандартный дистрибутив Apache, но также необходим еще файл конфигурации веб-сервера Apache htaccess. Вот это все что нам необходимо. Ссылка вида: http://servicefile/files/d58y1e составлена в соответствии с концепцией mod_rewrite. Но как происходит нам выдача на загрузку файла test.zip, если мы видим на первый взгляд ссылку невразумительного вида. Вот это мы сейчас и разберем более подробно.
От слов к делу
Конечно, для таких целей нужно использовать базу данных. Но в примере, который я приведу, мы ограничимся массивом. Писать скрипт будем на PHP. Я не буду разбирать загрузку файлов на сервер. Об этом и без моего участия написано достаточно. А приведу лишь конкретные примеры. Для получения загруженного файла на сервер, нам необходимо работать с глобальной переменной $_FILES, которая в свою очередь является массивом. Вот какие поля у нее есть:
$_FILES[‘file’][‘name’] |
Оригинальное имя файла |
$_FILES[‘file’][‘type’] |
Mime-тип файла |
$_FILES[‘file’][‘size’] |
Размер файла в байтах |
$_FILES[‘file’][‘tmp_name’] |
Временное имя файла на сервере. |
$_FILES[‘file’][‘error’] |
Код ошибки |
Возможные коды ошибок
0 |
UPLOAD_ERR_OK |
Ошибки нет |
1 |
UPLOAD_ERR_INI_SIZE |
Размер файла превышает допустимый размер, который задан директивой upload_max_filesize конфигурационного файла php.ini. |
2 |
UPLOAD_ERR_FORM_SIZE |
Размер загружаемого файла превысил значение MAX_FILE_SIZE, указанное в HTML-форме. |
3 |
UPLOAD_ERR_PARTIAL |
Загружаемый файл был получен только частично. |
4 |
UPLOAD_ERR_NO_FILE |
Файл не был загружен. |
Нам при обработке файла необходимо сохранить информацию из полей:
$_FILES['file']['name'] и $_FILES['file']['type'].
Далее нам необходимо создать файл конфигурации веб-сервера Apache htaccess. Со следующим содержанием:
#Директива RewriteEngine. Включает или выключает работу механизма преобразования.
RewriteEngine On
#Директива RewriteBase. Устанавливает базовый URL для преобразований в каталоге.
RewriteBase /# Ссылка на получение файла RewriteRule ^files/(.*)$ load.php?hash=$1 [L]
При отправке GET запроса вида: http://servicefile/files/d58y1e, происходит вот что. Сначала веб сервер Apache проверяет обязательно наличие файла htaccess в корне хоста. А именно в нашем случае в этом файле и находятся преобразования mod_rewrite, и если сервер находит соответствующее преобразование в этом модуле, то он перенаправляет запрос на соответствующий скрипт. В нашем случае, все происходит так: url который начинается с files/ далее идет набор произвольных символов. О чем свидетельствует выражение (.*). Набор произвольных символов идет до конца строки, т.е. до окончания url, все символы которые попадают под выражение (.*) – это наш hash, а именно “d58y1e”. В итоге скрипт load.php, получает значение параметра hash. Ниже приведен сам код скрипта:
<?php
// Путь до текущего каталога
define ( 'ROOT_DIR', dirname ( __FILE__ ) );
$files = array ();
$files['name'] = 'test.zip';
$files['type'] = 'application/zip';
$files['hash'] = 'd58y1e';
if (isset($_REQUEST['hash']) && $_REQUEST['hash'] != "";) {
$hash = $_REQUEST['hash'];
// Проверка на соответствие хеша
if ($files['hash'] == $hash) {
$fileName = ROOT_DIR . "/files/$files[name]";
$zip = '';
// Считываем нужный нам файл
$f = fopen($fileName, 'rb');
if ($f) {
$zip = fread($f, filesize($fileName));
}
fclose($f);
// Отправляем необработанные заголовки
header ( "Expires: Mon, 1 Apr 1974 05:00:00 GMT" );
header ( "Last-Modified: " . gmdate("D,d M YH:i:s") . " GMT" );
header ( "Cache-Control: no-cache, must-revalidate" );
header ( "Pragma: no-cache" );
header ( "Content-type: $files[type]" );
header ( "Content-Disposition: attachment; filename=$files[name]" );
// Выводим содержимое файла
print $zip;
}
}
?>
Теперь при открытие ссылки http://servicefile/files/d58y1e в браузере, браузер предложит скачать файл test.zip.
Единственное что я был заметил, так это то, что если вы хотите таким образом выдать ссылку на загрузку *.exe файла, то он относиться к бинарному (двоичному типу файлов) и соответственно имеет media-тип – application/octet-stream. Поэтому некоторые браузеры в таком случае предлагают сохранять такие файлы с расширением *.html (многие сервисы отдают файлы *.exe файлы в расширении *.html). Конечно, расширение файла можно переименовать и все будет отлично, ну лучше сделать дополнительную проверку на расширение файла и если он является исполняемым файлом операционной системы windows (*.exe) то присвоить в качестве значения media-типа – application/zip. Вы можете скачать полный исходник. Класс cURL прилагается.
Скрипт для скачивания файла
Меня уже давно интересовал вопрос, как например, при клике по ссылке вида: http://servicefile/files/d58y1e предлагается скачать файл к примеру с названием test.zip. По такому принципу работают файлообменники. Оказалось все достаточно просто. Сейчас я сделаю небольшое отступление.
Во времена статических web сайтов, у вебмастеров были весьма сильно связаны руки, не было возможности для реализации многих идей. Да и сайты кроме набора текста и пару картинок с баннерами, больше ничего из себя не представляли. Но времена изменились. И сейчас встретить в сети статический сайт становиться постепенно так же сложно, как раньше можно было бы встретить в сети сайт динамический. Но с появлением таких языков для веб программирования как PHP, ASP.NET и других, интернет в большой степени словно “обогатился”. Соответственно появилось очень большое количество технических возможностей по созданию веб сайтов. Раньше все в больше мере ограничивалось HTML в связке с JavaScript и редко с VBScript. Появились интернет магазины, электронные библиотеки, файлообменники, информационные порталы и другие, интересные и полезные веб ресурсы. Нет, конечно, они и раньше существовали, но это были не те магазины и порталы. И вот у владельце таких ресурсов возникла задача, а как сделать так, чтобы при выдаче ссылки на загрузку того или иного файла, не выдать реальное его местоположение. К примеру, файл, ссылка на который была представлена выше, физически находиться на servicefile/www/files/ и имеет имя test.zip. Как же так? Наверняка спросите вы, а все гениально просто. Есть такой очень и очень хороший модуль mod_rewrite который включается в стандартный дистрибутив Apache, но также необходим еще файл конфигурации веб-сервера Apache htaccess. Вот это все что нам необходимо. Ссылка вида: http://servicefile/files/d58y1e составлена в соответствии с концепцией mod_rewrite. Но как происходит нам выдача на загрузку файла test.zip, если мы видим на первый взгляд ссылку невразумительного вида. Вот это мы сейчас и разберем более подробно.
От слов к делу
Конечно, для таких целей нужно использовать базу данных. Но в примере, который я приведу, мы ограничимся массивом. Писать скрипт будем на PHP. Я не буду разбирать загрузку файлов на сервер. Об этом и без моего участия написано достаточно. А приведу лишь конкретные примеры. Для получения загруженного файла на сервер, нам необходимо работать с глобальной переменной $_FILES, которая в свою очередь является массивом. Вот какие поля у нее есть:
Возможные коды ошибок
Нам при обработке файла необходимо сохранить информацию из полей:
Далее нам необходимо создать файл конфигурации веб-сервера Apache htaccess. Со следующим содержанием:
#Директива RewriteEngine. Включает или выключает работу механизма преобразования.
RewriteEngine On
#Директива RewriteBase. Устанавливает базовый URL для преобразований в каталоге.
RewriteBase /# Ссылка на получение файла RewriteRule ^files/(.*)$ load.php?hash=$1 [L]
При отправке GET запроса вида: http://servicefile/files/d58y1e, происходит вот что. Сначала веб сервер Apache проверяет обязательно наличие файла htaccess в корне хоста. А именно в нашем случае в этом файле и находятся преобразования mod_rewrite, и если сервер находит соответствующее преобразование в этом модуле, то он перенаправляет запрос на соответствующий скрипт. В нашем случае, все происходит так: url который начинается с files/ далее идет набор произвольных символов. О чем свидетельствует выражение (.*). Набор произвольных символов идет до конца строки, т.е. до окончания url, все символы которые попадают под выражение (.*) – это наш hash, а именно “d58y1e”. В итоге скрипт load.php, получает значение параметра hash. Ниже приведен сам код скрипта:
Теперь при открытие ссылки http://servicefile/files/d58y1e в браузере, браузер предложит скачать файл test.zip.
Единственное что я был заметил, так это то, что если вы хотите таким образом выдать ссылку на загрузку *.exe файла, то он относиться к бинарному (двоичному типу файлов) и соответственно имеет media-тип – application/octet-stream. Поэтому некоторые браузеры в таком случае предлагают сохранять такие файлы с расширением *.html (многие сервисы отдают файлы *.exe файлы в расширении *.html). Конечно, расширение файла можно переименовать и все будет отлично, ну лучше сделать дополнительную проверку на расширение файла и если он является исполняемым файлом операционной системы windows (*.exe) то присвоить в качестве значения media-типа – application/zip. Вы можете скачать полный исходник. Класс cURL прилагается.