These days a customers website has generated a large amount of traffic because a client site has offered some “bigger” file downloads to their visitors. Normally there is nothing wrong with this kind of downloads on most of the websites, but in this case there are lot of visitors using a file download manager. With the most of these download clients it’s possible to enter a number of maximum connections for each target server. Just imagine if the visitor is using a value of “99″ for a file of only 10MB! This way one file download for one visitor will open 99 connections and the used bandwidth will be almost one gigabyte.

There is a apache module name mod_limitipconn which can handle this task, but what if the website is on some shared web hosting? In the last situation we need to write some extra function: In this small tutorial we are using some some mod_rewrite rule and a download script while the downloads are logged in a database.

First we need a database to store the file path, the IP address and the last download time:

CREATE TABLE IF NOT EXISTS `downloaded` (
`filepath` VARCHAR(255) NOT NULL,
`ipadres` VARCHAR(15) NOT NULL,
`last_access` DATETIME NOT NULL,
UNIQUE KEY `filepath` (`filepath`,`ipadres`),
KEY `ipadres` (`ipadres`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

For example you need to limit the downloads for files in a folder names “files”, place the file .htaccess file in this folder with this rewrite rule:

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

This rule rewrites every file access inside the folder (and sub folders) to the downloader script dl.php which is also located in the same folder “files”. Inside the downloader file we need to check if the file was downloaded from the IP address before:

$path = addslashes($_SERVER['REQUEST_URI']);
$ip = addslashes($_SERVER['REMOTE_ADDR']);
$dl = false;
$sql = sprintf("SELECT UNIX_TIMESTAMP(last_access) last_time FROM downloaded WHERE filepath = '%s' AND ipadres = '%s' ORDER BY last_access DESC", $path, $ip);
$res = mysql_query($sql);
if (mysql_num_rows($res) > 0) {
	$last_xs = mysql_result($res, 0, 'last_time')+3600;
	if ($last_xs < time()) {
		mysql_query(sprintf("REPLACE downloaded SET filepath = '%s', ipadres = '%s', last_access = NOW()", $path, $ip));
		$dl = true;
	}
} else {
	$sql = sprintf("REPLACE downloaded SET filepath = '%s', ipadres = '%s', last_access = NOW()", $path, $ip);
	mysql_query($sql);
	$dl = true;
}

We used in this example a time interval of 3600 seconds before it’s allowed to the user to download the file again. If the boolean variable $dl is “true” its allowed to download the file using this PHP code:

if ($dl) {
	$fullPath = $_SERVER['DOCUMENT_ROOT'].$path;
	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.');
}

This file download snippet is a very common example from the PHP manual. Notice that if the boolean variable is “false” no file download is possible and a forbidden message appears. Download the full code example here.