156

I was wondering how to make a PDF file link downloadable instead of opening them in the browser? How is this done in html? (I'd assume it's done via javascript or something).

MikeD
  • 5,004
  • 1
  • 25
  • 39
404Error
  • 1,643
  • 3
  • 15
  • 11
  • 3
    This is to my knowledge not scriptable behavior. Most browsers will have their own settings for the behavior of what to do with specific file types on download. – Bart Jul 22 '11 at 18:13
  • 1
    As of HTML5, the OP should update the correct answer to Sarim's answer. – Omar Tariq Sep 18 '13 at 07:32
  • possible duplicate of [Force to open "Save As..." popup open at text link click for pdf in HTML](http://stackoverflow.com/questions/3802510/force-to-open-save-as-popup-open-at-text-link-click-for-pdf-in-html) – Ciro Santilli OurBigBook.com Nov 06 '14 at 22:33
  • This question has also been answered here: http://stackoverflow.com/a/30714824/847235 – intrepidis Jun 10 '15 at 16:31

16 Answers16

160

With html5, it is possible now. Set a "download" attr in element.

<a href="http://link/to/file" download="FileName">Download it!</a>

Source : http://updates.html5rocks.com/2011/08/Downloading-resources-in-HTML5-a-download

Sarim
  • 3,124
  • 2
  • 20
  • 20
  • You better go with this solution if it's supported. Here's a way to check if it is `if ("download" in document.createElement("a")){ ... }` – pmrotule Dec 13 '15 at 02:30
  • i added another answer below (bad hack though), while this is still the preferred way, perhaps the hack way could be offered for unsupported browsers. – Sarim Jan 11 '16 at 19:51
  • Is there a way one can specify the text for the pdf instead of mentioning file path? I need to create pdf from a div html but I don't wish to open another window,download should be seemless like in this answer.. – T.Adak Oct 24 '16 at 11:53
  • 1
    As right now August 2019, Browser support seems to be enhanced for this feature, see: https://www.w3schools.com/tags/att_a_download.asp – Daniel Resch Aug 24 '19 at 21:51
  • 19
    Note that the download attribute is only supported for same-origin requests. – Quentin May 04 '20 at 17:29
96

This is only possible with setting a http response header by the server side code. Namely;

Content-Disposition: attachment; filename=fname.ext
Yiğit Yener
  • 5,796
  • 1
  • 23
  • 26
51

There is now the HTML 5 download attribute that can handle this.

I agree, and think Sarim's answer is good (it probably should be the chosen answer if the OP ever returns). However, this answer is still the reliable way to handle it (as Yiğit Yener's answer points out and--oddly--people agree with). While the download attribute has gained support, it's still spotty:

http://caniuse.com/#feat=download

TylerH
  • 20,799
  • 66
  • 75
  • 101
DA.
  • 39,848
  • 49
  • 150
  • 213
10

you will need to use a PHP script (or an other server side language for this)

<?php
// We'll be outputting a PDF
header('Content-type: application/pdf');

// It will be called downloaded.pdf
header('Content-Disposition: attachment; filename="downloaded.pdf"');

// The PDF source is in original.pdf
readfile('original.pdf');
?>

and use httacces to redirect (rewrite) to the PHP file instead of the pdf

beardhatcode
  • 4,533
  • 1
  • 16
  • 29
  • Hmm, it works great when I open the php file directly. But when I try to use redirection, like here: Redirect 301 /_PDFs/Catalogue.pdf `http://www.example.com/_PDFs/___download_the_catalogue_instead_opening.php` and try to open the pdf file, it still opens the original in the browser, instead downloading the renamed version... – ellockie Jul 14 '15 at 09:58
  • UPDATE: It works when there is no file that is being directly called (as "Catalogue.pdf" in my example). Then the redirection works perfectly. Thanks! – ellockie Jul 14 '15 at 10:16
9

You can use

Response.AddHeader("Content-disposition", "attachment; filename=" + Name);

Check out this example:

http://www.codeproject.com/KB/aspnet/textfile.aspx

This goes for ASP.NET. I am sure you can find similar solutions in all other server side languages. However there's no javascript solution to the best of my knowledge.

mihsathe
  • 8,904
  • 12
  • 38
  • 54
  • this is the answer ( as well as the related one for PHP). the point is that the http response header has to be edited. – user158017 Jul 25 '12 at 21:34
8

When you want to direct download any image or pdf file from browser instead on opening it in new tab then in javascript you should set value to download attribute of create dynamic link

    var path= "your file path will be here"; 
    var save = document.createElement('a');  
    save.href = filePath; 
    save.download = "Your file name here"; 
    save.target = '_blank'; 
    var event = document.createEvent('Event');
    event.initEvent('click', true, true); 
    save.dispatchEvent(event);
   (window.URL || window.webkitURL).revokeObjectURL(save.href);

For new Chrome update some time event is not working. for that following code will be use

  var path= "your file path will be here"; 
    var save = document.createElement('a');  
    save.href = filePath; 
    save.download = "Your file name here"; 
    save.target = '_blank'; 
    document.body.appendChild(save);
    save.click();
    document.body.removeChild(save);

Appending child and removing child is useful for Firefox, Internet explorer browser only. On chrome it will work without appending and removing child

Prasad Joshi
  • 471
  • 4
  • 12
4

Without html5 attribute one can achieve this by using php:

Create php file named download.php with this code:

<?php
ob_start();
$file = "yourPDF.pdf"

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

Now if you want to automatically start downloading pdf write this javascript:

<script>window.location = "download.php";</script>

If you want this to work on a link, use this...

<a href='javascript:window.location = "download.php"'>
    Download it!
</a>
hlozancic
  • 1,489
  • 18
  • 31
4

I've had some issues with the suggested solution that creates an a DOM element, and sets the download attribute. It still displayed a popup warning in some browsers (perhaps they got a little stricter by 2021).

Adding the pdf mime type to the href attribute solved the browser popup warning, but it messed up the file (the downloaded file got damaged and couldn't be opened).

In 2021 you can download a PDF file without browser warnings, without PHP or Apache settings, using an XMLHttpRequest as suggested by Edhowler. His code example uses an npm library though. Here's how to do it using js only:

/**
 * Download a file without browser popup warning
 * @param {string} url The url of the file to download
 * @param {string} filename Set a new filename for the downloaded file (optional)
 */
const downloadFile = (url, filename = '') => {
  if (filename.length === 0) filename = url.split('/').pop();
  const req = new XMLHttpRequest();
  req.open('GET', url, true);
  req.responseType = 'blob';
  req.onload = function () {
    const blob = new Blob([req.response], {
      type: 'application/pdf',
    });

    const isIE = false || !!document.documentMode;
    if (isIE) {
      window.navigator.msSaveBlob(blob, filename);
    } else {
      const windowUrl = window.URL || window.webkitURL;
      const href = windowUrl.createObjectURL(blob);
      const a = document.createElement('a');
      a.setAttribute('download', filename);
      a.setAttribute('href', href);
      document.body.appendChild(a);
      a.click();
      document.body.removeChild(a);
    }
  };
  req.send();
};

downloadFile('https://domain.tld/file.pdf');

Use a transpiler like Babel if you need support for non ES6+ browsers.

jnaklaas
  • 1,619
  • 13
  • 16
3

You can use download.js (https://github.com/rndme/download and http://danml.com/download.html). If the file is in an external URL, you must make an Ajax request, but if it is not, then you can use the function:

download(Path, name, mime)

Read their documentation for more details in the GitHub.

Vishnu S.
  • 141
  • 1
  • 2
  • 8
2

The solution that worked best for me was the one written up by Nick on his blog

The basic idea of his solution is to use the Apache servers header mod and edit the .htaccess to include a FileMatch directive that the forces all *.pdf files to act as a stream instead of an attachment. While this doesn't actually involve editing HTML (as per the original question) it doesn't require any programming per se.

The first reason I preferred Nick's approach is because it allowed me to set it on a per folder basis so PDF's in one folder could still be opened in the browser while allowing others (the ones we would like users to edit and then re-upload) to be forced as downloads.

I would also like to add that there is an option with PDF's to post/submit fillable forms via an API to your servers, but that takes awhile to implement.

The second reason was because time is a consideration. Writing a PHP file handler to force the content disposition in the header() will also take less time than an API, but still longer than Nick's approach.

If you know how to turn on an Apache mod and edit the .htaccss you can get this in about 10 minutes. It requires Linux hosting (not Windows). This may not be appropriate approach for all uses as it requires high level server access to configure. As such, if you have said access it's probably because you already know how to do those two things. If not, check Nick's blog for more instructions.

vtamm
  • 342
  • 1
  • 11
Strixy
  • 21
  • 1
2

As the html5 way (my previous answer) is not available in all browsers, heres another slightly hack way.

This solution requires you are serving the intended file from same domain, OR has CORS permission.

  1. First download the content of the file via XMLHttpRequest(Ajax).
  2. Then make a data URI by base64 encoding the content of the file and set media-type to application/octet-stream. Result should look like

data:application/octet-stream;base64,SGVsbG8sIFdvcmxkIQ%3D%3D

Now set location.href = data. This will cause the browser to download the file. Unfortunately you can't set file name or extension this way. Fiddling with the media-type could yield something.

See details: https://developer.mozilla.org/en-US/docs/Web/HTTP/data_URIs

Sarim
  • 3,124
  • 2
  • 20
  • 20
1

I needed to do this for files created with dynamic names in a particular folder and served by IIS.

This worked for me:

  • In IIS, go that folder and double click HTTP Response Headers.
  • Add a new header with the following info:

    Name: content-disposition Value: attachment

(from: http://forums.iis.net/t/1175103.aspx?add+CustomHeaders+only+for+certain+file+types+)

Andrei
  • 3,086
  • 2
  • 19
  • 24
EricL
  • 29
  • 3
1

If you are using HTML5 (and i guess now a days everyone uses that), there is an attribute called download.

ex. <a href="somepathto.pdf" download="filename">

here filename is optional, but if provided, it will take this name for downloaded file.

Akshay
  • 3,558
  • 4
  • 43
  • 77
  • Sadly, I have to admit that I am too stupid to understand this tag. I put this: `Download curriculum` or that: `Download curriculum` and I can see absolutely no difference in how it works. Both downloading my .zip. And in the second one using the filename option seems to do nothing at all. – Garavani Jun 02 '15 at 04:53
1

you can add the following code

<a href='http://v2.immo-facile.com/catalog/admin-v2/product_info.pdf' class='btnPdf' title='pdf'  target='_blank' type='application/pdf' >Télécharger la fiche du bien</a>
Nejmeddine Jammeli
  • 1,011
  • 9
  • 17
0

@Aljohn Yamaro

function forceDownload(pdf_url, pdf_name) {
    var x = new XMLHttpRequest();
    x.open("GET", pdf_url, true);
    x.responseType = 'blob';
    x.onload = function(e){
        saveAs(x.response, pdf_name, 'application/pdf');
    };
    x.send();
}
Edhowler
  • 715
  • 8
  • 17
0

The behaviour should depend on how the browser is set up to handle various MIME types. In this case the MIME type is application/pdf. If you want to force the browser to download the file you can try forcing a different MIME type on the PDF files. I recommend against this as it should be the users choice what will happen when they open a PDF file.

Aleksi Yrttiaho
  • 8,266
  • 29
  • 36