This script works in all browsers, including Internet Explorer! 🙂

Sometimes you need to force the browser to download a file instead of displaying it inline — PDFs and images are the usual culprits. The trick is setting the right combination of headers so the browser treats the response as a download rather than trying to render it.

The code below handles the IE-specific cache headers separately because older versions of Internet Explorer would choke on certain Cache-Control values. If you only need to support modern browsers, you can simplify this quite a bit. For larger files, consider adding chunked reading with fread() instead of readfile() to avoid memory issues.

if (strstr($_SERVER['HTTP_USER_AGENT'],"MSIE")) {
  header("Pragma: public");
  header("Expires: 0");
  header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
  header("Cache-Control: private",false);
  header("Content-Type: application-download");
  header("Content-Disposition: attachment; filename=\"".basename($filename)."\";");
  header("Content-Transfer-Encoding: binary");
  header("Content-Length: ".@filesize($ab_file));
  set_time_limit(0);
} else {
  header("Content-type: application-download");
  header("Content-Length: ".filesize($ab_file));
  header("Content-Disposition attachment; filename=".$filename);
}
readfile($ab_file);