PHPit - PHP

"Agora, pois, permanecem a fé, a esperança, o amor, estes três; mas o maior destes é o amor." (I Coríntios 13:13)

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
  1. CREATE TABLE `baixando` (
  2. `id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
  3. `arquivo` VARCHAR(255) NOT NULL,
  4. `ip` CHAR(15) NOT NULL,
  5. `ultimoacesso` DATETIME NOT NULL,
  6. ) 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:

RewriteEngine on
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
  1. <?php
  2.  
  3. // Aqui você deve fazer a conexão com o banco! :P
  4.  
  5. // Caminho do arquivo que está sendo requisitado
  6. $caminho = mysql_real_escape_string($_SERVER['REQUEST_URI']);
  7.  
  8. // IP do indivíduo que está requisitando o arquivo
  9. $ip = mysql_real_escape_string($_SERVER['REMOTE_ADDR']);
  10.  
  11. // Está baixando?
  12. $baixando = false;
  13.  
  14. // Seleciona o último acesso em formato UNIX, equivalente ao mktime()
  15. $sql = "SELECT UNIX_TIMESTAMP(ultimoacesso) AS ultimavez FROM baixando WHERE arquivo = '$caminho' AND ip = '$ip' ORDER BY ultimoacesso DESC LIMIT 1";
  16.  
  17. $rs = mysql_query($sql);
  18.  
  19. if (mysql_num_rows($rs)) {
  20. $ultimaVez = mysql_result($rs, 0, 'ultimoacesso') + 1800;
  21. if ($ultimaVez < time()) {
  22. mysql_query("REPLACE baixando SET caminho = '$caminho', ip = '$ip', ultimoacesso = NOW()");
  23. $baixando = true;
  24. }
  25. } else {
  26. $sql = "REPLACE baixando SET caminho = '$caminho', ip = '$ip', ultimoacesso = NOW()";
  27. mysql_query($sql);
  28. $baixando = true;
  29. }
  30. ?>
<?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($rs0'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
  1. <?php
  2. if ($baixar) {
  3. $caminhoCompleto = $_SERVER['DOCUMENT_ROOT'].$path;
  4. if ($fp = fopen($caminhoCompleto, 'r')) {
  5. header ('Content-disposition:attachment;filename="'.basename($caminhoCompleto).'";');
  6. header ('Content-Length: '.filesize($caminhoCompleto));
  7. readfile($caminhoCompleto);
  8. }
  9. } else {
  10. header('HTTP/1.0 503 Service Unavailable');
  11. print '<h1>503 Service Unavailable</h1><p>Você já baixou este arquivo demais!</p>';
  12. }
  13. ?>
<?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.

Dim dim

 

Comentaí! (10)

Bah cara... que massa isso aí, eu fazia idéia de mais ou menos como fazer, mas não imagina que seriam somente esses passos =)

GENIAL Xorna em 24/03/2008 às 20:47 utilizando o Mozilla Firefox Mozilla Firefox 2.0.0.12 no Windows Windows XP
A ideia é boa mas o seu codigo ................. Forbidencode em 19/08/2008 às 16:36 utilizando o Mozilla Firefox Mozilla Firefox 3.0 no Linux Linux
Olá Forbidencode.

Proponha uma abordagem melhor, por favor! :)

Um abraço! Rafael Jaques em 19/08/2008 às 16:43 utilizando o Mozilla Firefox Mozilla Firefox 3.0.1 no Windows Windows 2000
Tentei executar o script funciona tudo, porém quando vou baixar, ele me retorno esse erro:

[function.fopen]: failed to open stream: No such file or directory in C:\site\baixar.php on line 35

Oq pode ser?

Valeu Sou em 20/08/2008 às 01:00 utilizando o Mozilla Firefox Mozilla Firefox 2.0.0.16 no Windows Windows XP
Provavelmente não está encontrando o arquivo... Você pode tentar verificar se o caminho está certo no .htaccess e também nos diretórios do seu site! :) Rafael Jaques em 20/08/2008 às 09:03 utilizando o Mozilla Firefox Mozilla Firefox 3.0.1 no Windows Windows Vista
Consegui resolver o problema, porém estou com outro hehee
Quando acesso o script diretamente pelo browser. ex:

www.site.com.br/baixar.php

Ele pede para baixar o fonte do php hehe.
Porém o server está funcionando, rodando php normal o script está acessando o banco de dados, bloquecando a cada meia hora, tudo funciona.
Oq pode estár acontecendo?

Valeu Sou em 22/08/2008 às 15:43 utilizando o Mozilla Firefox Mozilla Firefox 3.0.1 no Linux Linux
Você fechou os parênteses sem ter aberto nenhum e vai dar merda ;D

$sql = "REPLACE baixando SET caminho = '$caminho', ip = '$ip', ultimoacesso = NOW()"); Cosme Fa em 15/12/2008 às 15:36 utilizando o Mozilla Firefox Mozilla Firefox 3.0.4 no Mac OS Mac OS X
Isso que dá escrever artigo na corrida! :P

Obrigado pelo comentário! Já arrumei! :) Rafael Jaques em 15/12/2008 às 16:13 utilizando o Mozilla Firefox Mozilla Firefox 3.0.4 no Windows Windows 2000
Olá, bom tuto, eu tenho um sistema gerador de link megaupload e gostaria de fazer algo do tipo. Usuario não pago pode gerar um link somente por dia. Como eu poderia fazer isto? Meu sistema é com curl. Gostaria de bloquear por usuario e não por IP, só meio leigo em PHP ainda. Você pode me dar uma luz? Obrigado Cristiano em 02/03/2010 às 15:07 utilizando o Mozilla Firefox Mozilla Firefox 3.5.8 no Windows Windows NT
Cara nao entendi nada do que li acima sou novo nesse negocio de internet mas viciado em jogos de pc assinei um serviço de net via radio e quando tento fazer download de jogos da uma msg "Impossivel fazer odownload desse arquivo HTTP/1.0 503 Service Unavailable" o que e isso e tem como resolver esse problema? Sandro em 21/04/2010 às 09:39 utilizando o Internet Explorer Internet Explorer 8.0 no Windows Windows NT
 

Comenta logo, pô!

* Todos os links inseridos nos comentários possuem rel="nofollow" para impedir com que crawlers considerem os mesmos como relevantes.
* Os e-mails não são divulgados.

Dados pessoais

Você é realmente um humano?

Finalmente, digite seu comentário :)

Caixinha de Sugestões

O que é isso? Aqui você pode simplesmente digitar uma sugestão (artigos, resenhas, melhorias, etc) sem precisar preencher longos formulários. Digite o que quiser na caixinha abaixo e eu lerei com o maior prazer! Se quiser se identificar, fique a vontade!

O PHPit é redigido e mantido por Rafael Jaques - Política de Privacidade.

XHTML/CSS desenvolvido por André Gazola.

PHPit 2007 - 2009 - Alguns direitos reservados.

Feeds ;)

Creative Commons License

PHPit por Rafael Jaques é licensiado sob a Creative Commons Atribuição-Uso Não-Comercial-Compartilhamento pela mesma Licença 2.5 Brasil License.