Force File Downloads instead of opening

There are times when you want to host some files but want people to download them instead of getting them opened by the default browser-defined action. This situation arises in cases when you are hosting pdf, image, or music files.  If you are using WordPress, you may use Download manager plugins for this effect but what happens when you are on a static website. There are .htaccess file hacks or apache tricks to achieve this. But not all Webhosting companies allow such mods or hacks. The one hack I am going to tell you will work no matter which web host you are using and will work on both blogs and static websites as well.

Step 1

First make a empty file and name it as download.php. Paste the following code into it:

<?php
$sourceFile = $_GET['file'];

if( headers_sent() ) 
  die('Headers Sent'); 

if(ini_get('zlib.output_compression')) 
  ini_set('zlib.output_compression', 'Off'); 

if (!is_file($sourceFile)) { die("<b>404 File not found!</b>"); }

$len = filesize($sourceFile);
$filename = basename($sourceFile);
$file_extension = strtolower(substr(strrchr($filename,"."),1));

switch( $file_extension ) {
  case "pdf"  : $ctype="application/pdf"; break;
  case "exe"  : $ctype="application/octet-stream"; break;
  case "zip"  : $ctype="application/zip"; break;
  case "doc"  : $ctype="application/msword"; break;
  case "xls"  : $ctype="application/vnd.ms-excel"; break;
  case "ppt"  : $ctype="application/vnd.ms-powerpoint"; break;
  case ".docx": $ctype="application/vnd.openxmlformats-officedocument.wordprocessingml.document"; break;
  case ".pptx": $ctype="application/vnd.openxmlformats-officedocument.presentationml.presentation"; break;
  case ".xlsx": $ctype="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; break;
  case "gif"  : $ctype="image/gif"; break;
  case "png"  : $ctype="image/png"; break;
  case "jpeg" :
  case "jpg"  : $ctype="image/jpg"; break;
  case "mp3"  : $ctype="audio/mpeg"; break;
  case "wav"  : $ctype="audio/x-wav"; break;
  case "mpeg" :
  case "mpg"  :
  case "mpe"  : $ctype="video/mpeg"; break;
  case "mov"  : $ctype="video/quicktime"; break;
  case "avi"  : $ctype="video/x-msvideo"; break;

  //The following are for extensions that shouldn't be downloaded
  case "php"  :
  case "css"  :
  case "js"   : 
  case "htm"  :
  case "html" :
  case "txt"  : die("<b>Cannot be used for ". $file_extension ." files!</b>"); break;

  default     : $ctype="application/force-download";
}

header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: public"); 
header("Content-Description: File Transfer");
header("Content-Type: $ctype");
$header="Content-Disposition: attachment; filename=".$filename.";";
header($header );
header("Content-Transfer-Encoding: binary");
header("Content-Length: ".$len);
@readfile($sourceFile);
exit;

Step 2

Now upload the file to your website … for example, I am considering the location as http://www.domain.com/download.php

Step 3

Now for linking to the file you want people to download forcibly, just point their links as http://www.domain.com/download.php?file=Filepath

Now, all files you link to like this will be forced to download from the visitor irrespective of the browser the user uses and of the web hosting you use.

Updated (11 October, 2012): I have updated and fixed the code above. It now supports newer Office file formats and also some video formats as well. Also, it won’t allow downloads of html, php, CSS-type files and also does some simple error checks.