Limitar descargas con Php

Por el 23 de febrero de 2008

en: Programacion

Probablemente no te encuentres con este problema pero si lo encuentras esta es una buena solución.

A menudo nos encontramos con sitios con un gran número de archivos para descargar, estos sitios limitan el número de descargas permitidas a sus visitantes.

En un principio no suele haber problemas si no limitas las descargas, pero si el visitante utiliza un “gestor de descargas” en los que puedes introducir un número de conexiones por archivo descargado, veras muy limitados los recursos de tu servidor.

Si tienes un control total de tu servidor puedes limitar de manera sencilla el número de descargas permitidas gracias al módulo mod_limitipconn, pero si tu sitio esta en un “hosting compartido” tendrás que tirar de ingenio para ponerle solución.

Paso 1: Base de Datos

En primer lugar necesitaremos una tabla con esta estructura en nuestra base de datos:

CREATE TABLE IF NOT EXISTS `descargas` (
`ruta` varchar(255) NOT NULL,
`ip` varchar(15) NOT NULL,
`ultimo_acceso` datetime NOT NULL,
UNIQUE KEY `ruta` (`ruta`,`ip`),
KEY `ip` (`ip`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

.htaccess

Neecesitamos colocar un archivo .htaccess en la carpeta a la que le queremos aplicar la limitación, por ejemplo “archivos”:

RewriteEngine on
RewriteRule (.*)(pdf|zip)$ /archivos/dl.php [QSA]

Script

Esta regla rescribe cada acceso al interior de la carpeta y lo redirecciona hacia el script dl.php que es el que chequeara los datos del visitante y gestionará el acceso a los archivos a descargar:

<?php
$ip = addslashes($_SERVER[‘REMOTE_ADDR’]);
$dl = false;
$sql = sprintf(“SELECT UNIX_TIMESTAMP(ultimo_acceso) ultima_vez
FROM descargas WHERE ruta = ’%s’ AND ip = ’%s’
ORDER BY ultimo_acceso DESC”, $ruta, $ip);
$res = mysql_query($sql);
if (mysql_num_rows($res) > 0) {
$last_xs = mysql_result($res, 0, ‘ultima_vez’)+3600;
if ($last_xs < time()) {
mysql_query(sprintf(“REPLACE descargas
SET ruta = ’%s’, ip = ’%s’, ultimo_acceso = NOW()”, $ruta, $ip));
$dl = true;
}
} else {
$sql = sprintf(“REPLACE descargas
SET ruta = ’%s’, ip = ’%s’, ultimo_acceso = NOW()”, $ruta, $ip);
mysql_query($sql);
$dl = true;
}
?>

Cómo puedes ver se ofrece un intervalo de 3.600 segundos antes de permitir de nuevo una descarga al usuario.

Si la variable $dl es “true” permitiremos acceso al siguiente script:

<??php
$fullPath = $_SERVER[‘DOCUMENT_ROOT’].$ruta;
if ($fd = fopen ($fullPath, “r”)) {
$fname = basename($fullPath);
header(‘Content-type: application/octet-stream’);
header(‘Content-Disposition: filename=”‘.$fname.‘”‘);
header(‘Content-length: ’.filesize($fullPath));
header(‘Cache-control: private’);
while(!feof($fd)) {
$buffer = fread($fd, 2048);
echo $buffer;
}
fclose ($fd);
exit;
}
} else {
header(‘HTTP/1.0 503 Service Unavailable’);
die(‘Abort, you reached your download limit for this file.’);
}

?>

Descarga el script completo

Esto es sólo una pequeña descripcion de este script que puedes encontrar completo aqui.

Dejar un comentario