1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

How to Force a Download *VERY USEFUL SCRIPT*

Discussion in 'PHP & Perl' started by Patrat, Nov 1, 2008.

  1. Patrat

    Patrat Junior Member

    Joined:
    Sep 20, 2008
    Messages:
    173
    Likes Received:
    549
    Occupation:
    Entrepreneur, Blogger & Internet Marketer
    Location:
    England, UK
    Say you want a PHP script that will make the browser download a file instead of opening it. This is useful for common filetypes that would normally be displayed in a browser, like .html, images, PDFs and .doc files.

    You can find a lot of scripts that do this on the web but one thing most of them don?t handle is download resuming and multi-thread downloading. If you don?t need that feature, feel free to use a simpler script. Personally I?ve found that a function that handles download resuming works more reliably across various browsers.

    HTML:
    function output_file($file, $name, $mime_type='')
    {
     /*
     This function takes a path to a file to output ($file), 
     the filename that the browser will see ($name) and 
     the MIME type of the file ($mime_type, optional).
     
     If you want to do something on download abort/finish,
     register_shutdown_function('function_name');
     */
     if(!is_readable($file)) die('File not found or inaccessible!');
     
     $size = filesize($file);
     $name = rawurldecode($name);
     
     /* Figure out the MIME type (if not specified) */
     $known_mime_types=array(
     	"pdf" => "application/pdf",
     	"txt" => "text/plain",
     	"html" => "text/html",
     	"htm" => "text/html",
    	"exe" => "application/octet-stream",
    	"zip" => "application/zip",
    	"doc" => "application/msword",
    	"xls" => "application/vnd.ms-excel",
    	"ppt" => "application/vnd.ms-powerpoint",
    	"gif" => "image/gif",
    	"png" => "image/png",
    	"jpeg"=> "image/jpg",
    	"jpg" =>  "image/jpg",
    	"php" => "text/plain"
     );
     
     if($mime_type==''){
    	 $file_extension = strtolower(substr(strrchr($file,"."),1));
    	 if(array_key_exists($file_extension, $known_mime_types)){
    		$mime_type=$known_mime_types[$file_extension];
    	 } else {
    		$mime_type="application/force-download";
    	 };
     };
     
     @ob_end_clean(); //turn off output buffering to decrease cpu usage
     
     // required for IE, otherwise Content-Disposition may be ignored
     if(ini_get('zlib.output_compression'))
      ini_set('zlib.output_compression', 'Off');
     
     header('Content-Type: ' . $mime_type);
     header('Content-Disposition: attachment; filename="'.$name.'"');
     header("Content-Transfer-Encoding: binary");
     header('Accept-Ranges: bytes');
     
     /* The three lines below basically make the 
        download non-cacheable */
     header("Cache-control: private");
     header('Pragma: private');
     header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
     
     // multipart-download and download resuming support
     if(isset($_SERVER['HTTP_RANGE']))
     {
    	list($a, $range) = explode("=",$_SERVER['HTTP_RANGE'],2);
    	list($range) = explode(",",$range,2);
    	list($range, $range_end) = explode("-", $range);
    	$range=intval($range);
    	if(!$range_end) {
    		$range_end=$size-1;
    	} else {
    		$range_end=intval($range_end);
    	}
     
    	$new_length = $range_end-$range+1;
    	header("HTTP/1.1 206 Partial Content");
    	header("Content-Length: $new_length");
    	header("Content-Range: bytes $range-$range_end/$size");
     } else {
    	$new_length=$size;
    	header("Content-Length: ".$size);
     }
     
     /* output the file itself */
     $chunksize = 1*(1024*1024); //you may want to change this
     $bytes_send = 0;
     if ($file = fopen($file, 'r'))
     {
    	if(isset($_SERVER['HTTP_RANGE']))
    	fseek($file, $range);
     
    	while(!feof($file) && 
    		(!connection_aborted()) && 
    		($bytes_send<$new_length)
    	      )
    	{
    		$buffer = fread($file, $chunksize);
    		print($buffer); //echo($buffer); // is also possible
    		flush();
    		$bytes_send += strlen($buffer);
    	}
     fclose($file);
     } else die('Error - can not open file.');
     
    die();
    }	
     
    /*********************************************
    			Example of use
    **********************************************/	
     
    /* 
    Make sure script execution doesn't time out.
    Set maximum execution time in seconds (0 means no limit).
    */
    set_time_limit(0);	
    $file_path='that_one_file.txt';
    output_file($file_path, 'some file.txt', 'text/plain');
    This script is very useful to as you can force people to download your pdf's, images etc but more importantly you can also bundle in PPI etc to earn some bucks.

    Summary: It will download the link instead of opening in a new window or tab.
     
  2. dating101

    dating101 Regular Member

    Joined:
    Aug 6, 2008
    Messages:
    440
    Likes Received:
    310
    Occupation:
    Out of work Construction Superintendent. Local rea
    Please excuse my ignorance, but how can a ppi be installed through this "forced" download?
     
  3. Patrat

    Patrat Junior Member

    Joined:
    Sep 20, 2008
    Messages:
    173
    Likes Received:
    549
    Occupation:
    Entrepreneur, Blogger & Internet Marketer
    Location:
    England, UK
    You just bind or bundle the files with PPI, then use fake file creators to rename the bundle to say something like ebook.pdf, and change the icon to a PDF one so it looks legit when the user looks at it.

    Then I have these in a folder on the server and when the user hovers over the link the location will say w3.website.c0m/files/ebook.pdf.

    If the force download script was not used the browser would display an error as it cannot reconise the file etc but with the download script it downloads it straight away instead.