How to make PDF file downloadable in HTML link?

Solution 1:

This is a common issue but few people know there's a simple HTML 5 solution:

<a href="./directory/yourfile.pdf" download="newfilename">Download the pdf</a>

Where newfilename is the suggested filename for the user to save the file. Or it will default to the filename on the serverside if you leave it empty, like this:

<a href="./directory/yourfile.pdf" download>Download the pdf</a>

Compatibility: I tested this on Firefox 21 and Iron, both worked fine. It might not work on HTML5-incompatible or outdated browsers. The only browser I tested that didn't force download is IE...

Check compatibility here: http://caniuse.com/#feat=download

Solution 2:

Instead of linking to the .PDF file, instead do something like

<a href="pdf_server.php?file=pdffilename">Download my eBook</a>

which outputs a custom header, opens the PDF (binary safe) and prints the data to the user's browser, then they can choose to save the PDF despite their browser settings. The pdf_server.php should look like this:

header("Content-Type: application/octet-stream");

$file = $_GET["file"] .".pdf";
header("Content-Disposition: attachment; filename=" . urlencode($file));   
header("Content-Type: application/octet-stream");
header("Content-Type: application/download");
header("Content-Description: File Transfer");            
header("Content-Length: " . filesize($file));
flush(); // this doesn't really matter.
$fp = fopen($file, "r");
while (!feof($fp))
{
    echo fread($fp, 65536);
    flush(); // this is essential for large downloads
} 
fclose($fp); 

PS: and obviously run some sanity checks on the "file" variable to prevent people from stealing your files such as don't accept file extensions, deny slashes, add .pdf to the value

Solution 3:

Don't loop through every file line. Use readfile instead, its faster. This is off the php site: http://php.net/manual/en/function.readfile.php

$file = $_GET["file"];
if (file_exists($file)) {
    header('Content-Description: File Transfer');
    header('Content-Type: application/octet-stream');
    header("Content-Type: application/force-download");
    header('Content-Disposition: attachment; filename=' . urlencode(basename($file)));
    // header('Content-Transfer-Encoding: binary');
    header('Expires: 0');
    header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
    header('Pragma: public');
    header('Content-Length: ' . filesize($file));
    ob_clean();
    flush();
    readfile($file);
    exit;
}

Make sure to sanitize your get variable as someone could download some php files...