Ограничение скорости скачивания файлов средствами PHP
Допустим, у нас есть сайт, предоставляющий файлы для скачивания. Но для зарегистрированных пользователей нет никаких ограничений, а для остальных, чтобы не перегружать сервер, хотелось бы ввести некоторые ограничения. Причина для ограничения скорости скачивания может быть и иной: пользователь, оплативший скачивание без ограничений - получает файл на максимальной скорости, а тот, кто пожадничал - будет скачивать очень медленно. Посмотрим, как это можно реализовать с помощью PHP:
// лимит времени выполнения
set_time_limit(0);
// скорость скачивания - 128КБ в сек.
$speed = 1024*128;
// имя файла
$filename = 'doc.pdf';
// размер файла
$filesize = filesize($filename);
// смещение от начала файла
$range = 0;
while( is_already_download() ) {
// спим пока у пользователя есть активные потоки
sleep(1);
}
// открываем файл на чтение
$f = fopen($filename, 'rb');
if (isset($_SERVER['HTTP_RANGE'])) { // поддерживается ли докачка
$range = $_SERVER['HTTP_RANGE'];
$range = str_replace('bytes=', '', $range);
$range = str_replace('-', '', $range);
if ($range) fseek($f, $range);
}
// если есть смещение
if ($range) {
header($_SERVER['SERVER_PROTOCOL'].' 206 Partial Content');
} else {
header($_SERVER['SERVER_PROTOCOL'].' 200 OK');
}
header( 'Last-Modified: '.date('D, d M Y H:i:s T', filemtime($filename)) );
header('Content-Length: '.($filesize-$range));
header('Accept-Ranges: bytes');
header('Content-Range: bytes '.$range.'-'.($filesize - 1).'/'.$filesize);
header('Content-Type: application/pdf');
header('Content-Disposition: attachment; filename="'.$filename.'"');
while( !feof($f) ) {
echo fread($f, $speed);
flush();
sleep(1); // засыпаем
}
// закрываем файл
fclose($f);
// удаляем информацию о соединении из БД
mysql_query("DELETE FROM `sessions` WHERE `session_ip`='".$_SERVER['REMOTE_ADDR']."' LIMIT 1");
function is_already_download() {
// проверяем на наличие соединений от пользователя
$res = mysql_query("SELECT `session_ip` FROM `sessions` WHERE `session_ip`='".$_SERVER['REMOTE_ADDR']."' LIMIT 1");
if (mysql_num_rows($res)) {
return true;
} else { // если запись отсутствует, то добавляем
mysql_query ("INSERT INTO `sessions` VALUES ('".$_SERVER['REMOTE_ADDR']."')");
return false;
}
}
?>
Однако пользователь без привилегий может воспользоваться менеджером закачки, который позволяет скачивать файл в несколько потоков. Таким образом, он сможет без труда обойти наше ограничение. На этот случай есть функция is_already_download(), которая проверяет наличие уже установленных соединений.
В данном случае мы используем таблицу БД sessions, в которй всего одно поле - IP-адрес скачивающего. При наличии IP-адреса скачивающего в таблице отдаем true, в противном случае записываем его и отдаем false.
Ссылки по теме:
Max Antonov:
Хотелось бы узнать, а зачем применять php для того, что делается средствами практически любого современного веб-сервера?
Если только забавы ради.
21 Апрель 2009, 16:17Я люблю PHP, но для таких целей его применять… простите, мазохизм!
LiC:
1) зато прикольно
2) не всегда есть возможность что-либо делать с настройками сервера. порой встечаются весьма “специфические” хостеры (особенно забугорные)
автору - респект ))
22 Апрель 2009, 9:17Разработчик XHTML:
Интересно.
25 Апрель 2009, 19:04тима:
не так сложно как кажется на первый взгляд. Внедрить довольно просто и быстро.
13 Май 2009, 11:49Piter:
Все-так ограничивать такие скачки нужно, а то смысл тогда всей регистрации пропадет.
9 Июнь 2009, 10:28ShadX:
Если привязываться к серверу *настройкам*, то при смене хостера будут грабли. А так решение небольшое и в принципе безгеморное …
24 Февраль 2010, 22:15Надо будет попробовать …
Лучезар:
Горшков Алексей Геннадьевич…
Горшков Алексей Геннадьевич …
23 Апрель 2010, 17:47Frankie:
Good afternoon! Please e-mail me your contacts. I have a question eric@ollitehnika.ru” rel=”nofollow”>……
Thanks!…
12 Июнь 2010, 16:50