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:
Very useful technique. Thanks for sharing.
Its a nice idea but the problem with this is it puts a lot more strain on the server.
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.
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
@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.
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.
It doesn’t work for me. Any help? :/
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.