Using PHP to limit download speed

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • chipgraphics
    New Member
    • Oct 2005
    • 8

    Using PHP to limit download speed

    :confused::conf used:

    I have been on the quest to find a php script that can serve files for downloads and limit the speed at which the file is transfered to the user. I want a faster download speed for registered members and a slower speed for guests.

    The only other thing I can think of is using the header() function to force a download for the requested file type and stream the file to the user's browser. Then using sleep() or usleep() on a loop until the download completes.

    Anyone have any suggestions or ideas?

    ~Chipgraphics
  • Niheel
    Recognized Expert Moderator Top Contributor
    • Jul 2005
    • 2433

    #2
    Here is a snippet i found on php.net.

    Code:
    [font=Courier New]<?php
    
    $file = "test.mp3"; [/font][font=Courier New]// file to be send to the client
    $speed = 8.5; [/font][font=Courier New]// 8,5 kb/s download rate limit
    
    if(file_exists($file) && is_file($file[/font][font=Courier New])) {
    
       header("Cache-control: private"[/font][font=Courier New]);
       header("Content-Type: application/octet-stream"[/font][font=Courier New]); 
       header("Content-Length: ".filesize($file[/font][font=Courier New]));
       header("Content-Disposition: filename=$file" . "%20"[/font][font=Courier New]); 
    
       flush[/font][font=Courier New]();
    
       $fd = fopen($file, "r"[/font][font=Courier New]);
       while(!feof($fd[/font][font=Courier New])) {
    		 echo fread($fd, round($speed*1024[/font][font=Courier New]));
    	   flush[/font][font=Courier New]();
    	   sleep(1[/font][font=Courier New]);
       }
       fclose ($fd[/font][font=Courier New]);
    
    }
    ?> [/font]
    Link to page and exact code.
    niheel @ bytes

    Comment

    • chipgraphics
      New Member
      • Oct 2005
      • 8

      #3
      I combined a couple together and tweaked them out and it works!

      With the constant change of protocols and programming yada yada. I read over what you had suggested and combined a couple of the concepts into one package deal. And it worked on the first try ! :D So, thank you for pointing me in the right direction ! I'll list my source code below.

      Here's a function to use PHP to control download bandwith speed:
      All original code I borrowed from PHP's online documentation found HERE.

      Code:
      <?php
      function send_file($file, $speed = 100) {
      	
      	//First, see if the file exists  
      	if (!is_file($file)) {
      		die("<b>404 File not found!</b>");
      	}  
      	//Gather relevent info about file
      	$filename = basename($file);
      	$file_extension = strtolower(substr(strrchr($filename,"."),1));
      	// This will set the Content-Type to the appropriate setting for the file
      	switch( $file_extension ) {
      		case "exe":
      			$ctype="application/octet-stream";
      			break;
      		case "zip":
      			$ctype="application/zip";
      			break;
      		case "mp3":
      			$ctype="audio/mpeg";
      			break;
      		case "mpg":
      			$ctype="video/mpeg";
      			break;
      		case "avi":
      			$ctype="video/x-msvideo";
      			break;
      	   
      		//  The following are for extensions that shouldn't be downloaded
      		// (sensitive stuff, like php files)
      		case "php":
      		case "htm":
      		case "html":
      		case "txt":
      			die("<b>Cannot be used for ". $file_extension ." files!</b>");
      			break;
      		default:
      			$ctype="application/force-download";
      	}
      
      	//  Begin writing headers
      	header("Cache-Control:");
      	header("Cache-Control: public");
      	header("Content-Type: $ctype");
      
      	$filespaces = str_replace("_", " ", $filename);
      	// if your filename contains underscores, replace them with spaces
      
      	$header='Content-Disposition: attachment; filename='.$filespaces;
      	header($header);
      	header("Accept-Ranges: bytes");
         
      	$size = filesize($file);  
      	//  check if http_range is sent by browser (or download manager)  
      	if(isset($_SERVER['HTTP_RANGE'])) {
      		// if yes, download missing part	 
      
      		$seek_range = substr($_SERVER['HTTP_RANGE'] , 6);
      		$range = explode( '-', $seek_range);
      		if($range[0] > 0) { $seek_start = intval($range[0]); }
      		if($range[1] > 0) { $seek_end  =  intval($range[1]); }
      		   
      		header("HTTP/1.1 206 Partial Content");
      		header("Content-Length: " . ($seek_end - $seek_start + 1));
      		header("Content-Range: bytes $seek_start-$seek_end/$size");
      	} else {
      		header("Content-Range: bytes 0-$seek_end/$size");
      		header("Content-Length: $size");
      	}  
      	//open the file
      	$fp = fopen("$file","rb");
         
      	//seek to start of missing part  
      	fseek($fp,$seek_start);
        
      	//start buffered download
      	while(!feof($fp)) {	  
      		//reset time limit for big files
      		set_time_limit(0);	  
      		print(fread($fp,1024*$speed));
      		flush();
      		sleep(1);
      	}
      	fclose($fp);
      	exit;
      }
      ?>
      I hope that helps someone out too. Thanks again for pointing me in the right direction !!


      ~Chipgraphics

      Comment

      • Niheel
        Recognized Expert Moderator Top Contributor
        • Jul 2005
        • 2433

        #4
        Hey, congrats on getting the results you were looking for.

        Thanks for posting the code for people to learn from, that's what this forum is all about.


        ~KUB
        niheel @ bytes

        Comment

        • Flegma
          New Member
          • Mar 2006
          • 2

          #5
          I used that script from php.net but i have a problem. When i click on download it starts download, but on ~600kB it stops and dont download....
          can abybody explain me thit??

          Comment

          • Niheel
            Recognized Expert Moderator Top Contributor
            • Jul 2005
            • 2433

            #6
            Download issues from their server. Maybe wait for a few hrs and try again.
            niheel @ bytes

            Comment

            • Flegma
              New Member
              • Mar 2006
              • 2

              #7
              Originally posted by KUB365
              Download issues from their server. Maybe wait for a few hrs and try again.
              it is localhost.....
              can it be some option of apache ???
              in my webhosting i tried to download 20 MB and it was OK....

              Comment

              • pezhvak
                Banned
                New Member
                • Jul 2009
                • 17

                #8
                resolve download limit problem

                Originally posted by Flegma
                I used that script from php.net but i have a problem. When i click on download it starts download, but on ~600kB it stops and dont download....
                can abybody explain me thit??
                it's because php stops your script (your script will timeout).. to avoid it, copy following code in the top of your script:

                set_time_limit( 99999999);

                Comment

                • s1dest3pnate
                  New Member
                  • Sep 2009
                  • 2

                  #9
                  I'm pretty new to PHP. Where in this file would I include the name of the file that I want the user to download or is there a different way to set what file to use this script for? Thanks in advance!

                  Comment

                  • Dormilich
                    Recognized Expert Expert
                    • Aug 2008
                    • 8694

                    #10
                    the file name is the function’s first parameter.

                    Comment

                    • s1dest3pnate
                      New Member
                      • Sep 2009
                      • 2

                      #11
                      My fault. I meant in chipgraphics code.

                      I would assume I would input the filename somewhere in this line:

                      Code:
                      $filename = basename($file);
                      If not, where?

                      Thanks in advance.

                      Comment

                      • Dormilich
                        Recognized Expert Expert
                        • Aug 2008
                        • 8694

                        #12
                        Code:
                        function send_file([U]$file[/U], $speed = 100) {
                        as can be deduced from line 5 to 9.

                        Comment

                        • xphile
                          New Member
                          • Dec 2009
                          • 1

                          #13
                          Browser hangs!

                          This code works on my station only if I comment sleep statement! Otherwise browser waiting for file but download doesn't starts. Why?
                          System: Debian squeeze 2.6.31.6 / Apache 2.2.14-3 / PHP 5.2.1

                          Comment

                          Working...