Limitando o número de downloads por cliente / pessoa / usuário / IP
Prefácio
Rapidshare, MegaUpload, EasyShare, Zupload, Uploading, 4Shared... Quem nunca usou nenhum destes serviços que atire a primeira pedra. Não é tão intrigante o modo como eles conseguem fazer com que baixemos apenas um arquivo por vez? É muito bom saber que você consegue poupar uma porção de banda limitando o número de downloads cabeça!Esta solução também provê um fim para o download utilizando aceleradores! :)
Os mais puristas irão indicar o módulo mod_limitipconn do Apache, mas se você estiver em uma hospedagem compartilhada, na maioria das vezes você não poderá mexer nos módulos do Apache.
Nessa dica iremos utilizar o mod_rewrite e um scriptzinho que irá gerenciar os downloads. Este também poderá ser adaptado para funcionar da mesma forma que o script gerenciador de downloads que foi desenvolvido em um dos últimos artigos, Forçar download ao invés da exibição.
Quem irá cuidar dos acessos de cada usuário será o nosso bom e velho MySQL (claro que você pode adaptar para PostgreSQL, Oracle, MS SQL Server, etc).
Mão na massa
A primeira coisa de todas é criar a nossa querida tabela. Vamos dar à ela o nome de baixando.Código: Alternar entre o modo de cópia e de destaque
CREATE TABLE `baixando` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, `arquivo` VARCHAR(255) NOT NULL, `ip` CHAR(15) NOT NULL, `ultimoacesso` DATETIME NOT NULL, ) ENGINE=InnoDB
Agora precisamos do arquivo .htaccess. Caso você ainda não o conheça, você pode ler mais sobre ele neste artigo: Sobrescrevendo as configurações do php.ini com Apache e .htaccess.
Bom... Vamos supor que todos os arquivos estejam dentor da pasta arquivos. Você irá salvar o arquivo .htaccess neste diretório contendo as seguintes linhas:
RewriteRule (.*)(zip|rar|pdf|exe)$ /arquivos/baixar.php [QSA]
Esta regra irá capturar todos os arquivos que forem acessados neste diretório, terminados em (zip|rar|pdf|exe), e irá cuidar para que todos eles sejam redirecionados para o arquivo baixar.php. É neste arquivo que devemos fazer a configuração para verificar se o fulano que está acessando tem permissão para tal.
E vamos à parte que estamos "acostumados":
Código: Alternar entre o modo de cópia/destaque
<?php // Aqui você deve fazer a conexão com o banco! :P // Caminho do arquivo que está sendo requisitado // IP do indivíduo que está requisitando o arquivo // Está baixando? $baixando = false; // Seleciona o último acesso em formato UNIX, equivalente ao mktime() $sql = "SELECT UNIX_TIMESTAMP(ultimoacesso) AS ultimavez FROM baixando WHERE arquivo = '$caminho' AND ip = '$ip' ORDER BY ultimoacesso DESC LIMIT 1"; $baixando = true; } } else { $sql = "REPLACE baixando SET caminho = '$caminho', ip = '$ip', ultimoacesso = NOW()"; $baixando = true; } ?>
<?php
// Aqui você deve fazer a conexão com o banco! :P
// Caminho do arquivo que está sendo requisitado
$caminho = mysql_real_escape_string($_SERVER['REQUEST_URI']);
// IP do indivíduo que está requisitando o arquivo
$ip = mysql_real_escape_string($_SERVER['REMOTE_ADDR']);
// Está baixando?
$baixando = false;
// Seleciona o último acesso em formato UNIX, equivalente ao mktime()
$sql = "SELECT UNIX_TIMESTAMP(ultimoacesso) AS ultimavez FROM baixando WHERE arquivo = '$caminho' AND ip = '$ip' ORDER BY ultimoacesso DESC LIMIT 1";
$rs = mysql_query($sql);
if (mysql_num_rows($rs)) {
$ultimaVez = mysql_result($rs, 0, 'ultimoacesso') + 1800;
if ($ultimaVez < time()) {
mysql_query("REPLACE baixando SET caminho = '$caminho', ip = '$ip', ultimoacesso = NOW()");
$baixando = true;
}
} else {
$sql = "REPLACE baixando SET caminho = '$caminho', ip = '$ip', ultimoacesso = NOW()";
mysql_query($sql);
$baixando = true;
}
?>
Neste exemplo é utilizado um intervalo de 1800 segundos (meia hora) antes que o usuário possa baixar este arquivo novamente. Se o valor de $baixando for true.
E então segue o código que irá gerenciar o download! :)
Código: Alternar entre o modo de cópia/destaque
<?php
if ($baixar) {
$caminhoCompleto = $_SERVER['DOCUMENT_ROOT'].$path;
if ($fp = fopen($caminhoCompleto, 'r')) {
header ('Content-disposition:attachment;filename="'.basename($caminhoCompleto).'";');
header ('Content-Length: '.filesize($caminhoCompleto));
readfile($caminhoCompleto);
exit;
}
} else {
header('HTTP/1.0 503 Service Unavailable');
print '<h1>503 Service Unavailable</h1><p>Você já baixou este arquivo demais!</p>';
exit;
}
?>
Com este código, o download só será possível se já tiver passado meia hora após a última vez em que este IP efetuou o download. E daí é só correr pro abraço! :P
Conclusão
Não é difícil de montar um sistema assim. Como em todos os tutoriais aqui, você pode desenvolver novas implementações e aumentar o potencial do script. Caso você utilize estes scripts como base ou caso você encontre algum erro, adoraria receber um comentário ou um e-mail seu!Um grande abraço e fiquem com Deus.
PHP levado a sério