Here is a speed limit solution for download. You can use same for upload. .i.e.read the file into smaller chunk and then upload each chunk with sleep :)
Let’s assume we want to limit the bandwidth 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.