Контролируемая отдача файлов
Разделяй и властвуй...
Этому дала, этому дала... а этому не дала...
Если у Вас возникла потребность в отдаче (выгрузке) файлов Вашим пользователям, и Вы хотите контролировать кому,
с какой скоростью и сколько отдать, предлагаю Вам свой php-класс. Данный класс есть сборная солянка чужого кода под
моей редакцией и улучшениями. Копирайты не привожу, т.к. за частую трудно определить, кому именно принадлежало право
первенства на тот или иной кусок кода, да и заниматься вычислением авторов специально желания нет. По сему заранее
приношу неизвестным авторам извинения за плагиат :). Но меня, как практикующего программиста, интересовал в первую
очередь результат.
Короче: всем желающим/страждущим, кому не хочется переводить свое время на изобретение велосипеда, предлагаю
воспользоваться моим.
Описание
Представленный ниже класс позволяет:
- разрешать/запрещать докачку файлов;
- ограничивать скорость отдачи (по умолчанию 5 Кб);
- отдавать файлы пользователям по именам, передаваемым в класс (авторизация оных ложится на Ваши плечи - класс
только принимает имя пользователя и по нему считает объем). Для каждого пользователя в папке stats (по умолчанию)
заводится своя папка по имени пользователя. Из имени пользователя регэкспом вырезается все кроме "0-9a-zA-Z_-". Для
каждого IP-адреса заводится соответствующий файл (например: 10.1.3.94) в который в течение времени работы скрипта
записывается скачанный объем. По этому файлу собственно и осуществляется контроль отдаваемого объема. Удаление/обнуление
файла классом не производится - если Вам это нужно - допишите сами.
- разрешать/запрещать отдачу файлов по списку стран, IP-адресов. Во всех списках разделитель запятая, все знаки (в т.ч.
пробелы учитываются!). Локалхост и локальные адреса (192.168.xxx.xxx, 10.xxx.xxx.xxx, 172.16.xxx.xxx) именуются как
localhost и Local network соответственно. Определение страны по IP-адресу осуществляется через сервис whois.ripe.net.
Скачать одним архивом: download.rar
Пример:
Файл 1.php. Качаем линк http://serv/1.php?download=docucd_v210_[iso].zip
enabledCountry = 'localhost,Local network,UA,RU';
$Download->whiteList = '127.0.0.1,10.1.3.94';
$Download->banList = '184.12.13.5';
$Download->userName = 'pupkin';
$Download->speedLimit = 10;
$Download->sizeLimit = 2*MB;
$Download->downloadFile();
?>
Код класса
fileName = $fileName;
if ($userName)
$this->userName = ereg_replace('[^0-9a-zA-Z_\-]','',$userName).'/';
$fullPath = $this->statFolder.$this->userName;
if (!file_exists($fullPath))
mkdir($fullPath);
} # End CDownload
function verifyCountry() {
$userCountry = $this->getCountry($_SERVER['REMOTE_ADDR']);
if (
($this->enabledCountry && !in_array($userCountry,split(',',$this->
enabledCountry))) ||
($this->disabledCountry && in_array($userCountry,split(',',$this->
disabledCountry))) ||
($this->whiteList && !in_array($_SERVER['REMOTE_ADDR'],split(',',$this->
whiteList))) ||
($this->banList && in_array($_SERVER['REMOTE_ADDR'],split(',',$this->
banList)))
) {
header('HTTP/1.0 403 Forbidden');
header('Warning: 99# You country or IP address disabled');
exit;
}
}
function downloadFile() {
$this->verifyCountry();
$blockSize = 8192;
$headerErrorText = 'Error! A possible size is exceeded';
$this->userName = ereg_replace('[^0-9a-zA-Z_\-]','',$this->userName).'/';
$this->fileName = preg_replace('/\.{2}/','',$this->fileName);
if (!file_exists($this->fileName)) {
header('HTTP/1.0 404 Not Found');
exit;
}
$fsize = filesize($this->fileName);
$ftime = date('D, d M Y H:i:s T', filemtime($this->fileName));
$fd = @fopen($this->fileName, 'rb');
if (!$fd) {
header('HTTP/1.0 403 Forbidden');
exit;
}
if ($this->enablePartial && ereg('bytes=([0-9]+)-',$_SERVER['HTTP_RANGE'],$range)) {
header('HTTP/1.1 206 Partial Content');
$range = $range[1];
fseek($fd, $range);
} else
header('HTTP/1.1 200 OK');
$fullPath = $this->statFolder.$this->userName;
$this->transferBytes = file($fullPath.$_SERVER['REMOTE_ADDR']);
$this->transferBytes = $this->transferBytes[0];
if ($this->sizeLimit && $this->transferBytes>$this->sizeLimit) {
header('HTTP/1.0 403 Forbidden');
header('Warning: 99# '.$headerErrorText);
exit;
}
$fp = fopen($fullPath.$_SERVER['REMOTE_ADDR'],'w');
header('Content-Disposition: attachment; filename='.ereg_replace('^.*/','',
$this->fileName));
header('Last-Modified: '.$ftime);
header('Accept-Ranges: bytes');
header('Content-Length: '.($fsize-$range));
header('Content-Range: bytes '.$range.'-'.($fsize-1).'/'.$fsize);
header('Content-type: application/octet-stream');
set_time_limit($this->downloadTimeLimit);
while (!feof($fd)) {
if ($this->sizeLimit && $this->transferBytes>$this->sizeLimit) {
header('Warning: 99# '.$headerErrorText);
exit;
}
echo fread($fd, $blockSize);
$this->transferBytes += $blockSize;
fseek($fp,0);
fwrite($fp,$this->transferBytes);
if ($this->speedLimit)
usleep(8000000/$this->speedLimit);
}
fclose($fp);
fclose($fd);
} # End downloadFile
function getCountry($ip) {
$result = 'Unknow';
if (ereg('127\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}',$ip))
return 'localhost';
if (ereg('10\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}|191\.168\.[0-9]{1,3}\.[0-9]{1,3}|'.
'172\.16\.[0-9]{1,3}\.[0-9]{1,3}',$ip))
return 'Local network';
if ($ip!='') {
$sock = fsockopen('whois.ripe.net',43,$errno,$errstr);
if ($sock) {
fputs ($sock,$ip."\r\n");
while (!feof($sock) && !preg_match('/country:\s*(\S*)/',$buf,$matches))
$buf = fgets($sock,128);
$result = strtoupper($matches[1]);
}
fclose ($sock);
}
return $result;
} # End getCountry
}
?>
Автор: Гаенко Дмитрий
Источник: www.gaenko.net.ua
|