Bandwidth limit script

Sometimes you want to limit the bandwidth for certain ips or sites, in order to keep your traffic within limits, or to keep constant bandwidth to all users, regardless of how much they are downloading.

Here is a solution to do that:

Let’s assume we want to limit the bandwith for images found in /images/ folder.

First, we need a bandwidth php script, in which we setup the limit of the downloading speed. We achieve that by reading small packets from the file requested, with a timeout between readings:

<?php
//Enter the bandwidth here
$bandwidth = '32'; // KB/s
//For security reason, we will add here all the pattern that we allow for the filename
//Change this to your own needs
$allowed_file_patterns = array('/images\/(\w+)\.(jpg|gif|jpeg|png)/i');
 
function getMimeType($file_path)
{
	$mtype = '';
	if (function_exists('mime_content_type')){
    	$mtype = mime_content_type($file_path);
  	}
	elseif (function_exists('finfo_file')){
    	$finfo = finfo_open(FILEINFO_MIME);
    	$mtype = finfo_file($finfo, $file_path);
    	finfo_close($finfo);
  	} elseif (function_exists('getimagesize')){
		$finfo = @getimagesize($file_path);
		//var_dump($finfo);
		$mtype = !empty($finfo['mime'])?$finfo['mime']:'';
	}
	if ($mtype == ''){
    	     $mtype = "application/force-download";
  	}
	return $mtype;
}
$accepted_pattern = false;
foreach ($allowed_file_patterns as $pattern){
	if (preg_match($pattern,$_GET['file'])){
		$accepted_pattern = true;
	}
}
if (!$accepted_pattern){
    //Stop the script if is not a valid access
	header("HTTP/1.1 403 Forbidden");
	echo 'Forbidden request';
	exit;
 
}
 
$fileName = $_GET['file'];
$fh = @fopen($fileName,'rb');
if (!$fh){
	echo 'Unable to open file';
	exit;
}
$fileSize = filesize($fileName);
header("Content-Type: ".getMimeType($fileName));
header("Content-Length: " . $fileSize);
while(!feof($fh))
{
	//Read the allowed bandwidth, and then just wait a second
	print(fread($fh, $bandwidth*1024));
	usleep(1000000);
}
fclose($fh);
?>

Now, you can create an .htaccess file, to redirect all the requests you need to be limited, to that bandwidth script:

RewriteEngine on
RewriteCond %{REQUEST_URI} \.(gif|jpg|jpeg|png|GIF|JPG|JPEG|PNG)$
RewriteRule (.*) bandwidth.php?file=$1 [L]

If you want you can limit the bandwidth only for some ip’s or some referals. In the htaccess file you will have:

RewriteEngine on
 
#Enter the ip's or class of ip's you want to limit bellow, with [OR] between them
#All the other ip's will access the url directly, without going through bandwidth.php
RewriteCond %{REMOTE_ADDR} ^123\.45\.6\.78$ [NC,OR]
RewriteCond %{REMOTE_ADDR} ^127\.0\.0 [NC]
RewriteCond %{REQUEST_URI} \.(gif|jpg|jpeg|png|GIF|JPG|JPEG|PNG)$
RewriteRule (.*) bandwidth.php?file=$1 [L]
 
#Enter the ip's or class of ip's you want to limit bellow, with [OR] between them
#All the other ip's will access the url directly, without going through bandwidth.php
RewriteCond %{HTTP_REFERER} ^http://(www\.)?php-code.net/.*$ [NC,OR]
RewriteCond %{HTTP_REFERER} ^http://(www\.)?example.com/.*$ [NC]
RewriteCond %{REQUEST_URI} \.(gif|jpg|jpeg|png|GIF|JPG|JPEG|PNG)$
RewriteRule (.*) bandwidth.php?file=$1 [L]

In this way you can limit the traffic from leecher sites, without forbidden them, which I think is a more elegant solution.

Attached you can find Bandwidth limiter script used in this article.

Also, you can  try a demo (set a limit, and play with the downloading to see how fast it goes)

Related posts:

  1. How to change your site url structure
  2. .htaccess stupid tricks

8 Responses to “Bandwidth limit script”

  1. iTechRoom says:

    Very useful technique. Thanks for sharing.

  2. Michael says:

    Its a nice idea but the problem with this is it puts a lot more strain on the server.

  3. dan says:

    Michael, i know that reading the file from PHP, instead of reading it directly from disk, will put more strain on the server, which is why i recommended to adopt this solution only for referers or ips who actually steals a lot of content from you.
    .htaccess should redirect the request to the actual file (not php) for all the other legitimate requests.

  4. aargoth says:

    There is much better solution than posted above:

    Check Qualito of Service Bandwidth Trottler class for PHP:

    http://webscripts.softpedia.com/script/PHP-Clases/QoS-Bandwidth-Throttler-66826.html

  5. dan says:

    @aargoth : There are many scripts which offers better solutions – i was not trying to make it perfect, just to keep it simple enough so the readers can understand how can you achieve bandwith limit using php.

  6. Good write-up, I am normal visitor of one¡¦s blog, maintain up the nice operate, and It is going to be a regular visitor for a long time.

  7. Aldo says:

    It doesn’t work for me. Any help? :/

  8. ali says:

    can i used for a specific user e.g. i have a website where i want that
    Access could be tied to days (from first log on with the access code), and if possible bandwidth used by customer-if they exceed the necessary bandwidth, they will be log off.

Leave a Reply