1

The code is very simple:

<a download href="http://www.pdf995.com/samples/pdf.pdf">Download</a>

I expect it to save the pdf file but it always open the file on the browser.

It works with other file type, just have problem with PDF file.

Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
Thach Nguyen
  • 76
  • 1
  • 7
  • 2
    I believe this is something configurable in the browser side. You can choose weather to download or visualize a PDF – manelescuer Apr 05 '18 at 09:08
  • Can you add more context? What browser/platform? Are you stopping it via JS? – evolutionxbox Apr 05 '18 at 09:10
  • Does this answer your question? [PDF file not downloading with HTML5 download attribute](https://stackoverflow.com/questions/51861852/pdf-file-not-downloading-with-html5-download-attribute) – KOalaDelYtaPLaYa Sep 05 '20 at 08:36

2 Answers2

7

See the MDN documentation:

This attribute only works for same-origin URLs.

Presumably, the other file types, where you see it "working", are ones where the default behaviour is to download the file.

Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
  • I'm not sure but maybe you're right. Anyway, I worked around by fetch the blob data and build the file url locally to download. – Thach Nguyen Apr 06 '18 at 04:52
3

If the URL that you're trying to fetch has an Access-Control-Allow-Origin header, you can work around this by using fetch and blobs:

function forceDownload(blob, filename) {
  // Create an invisible anchor element
  const anchor = document.createElement('a');
  anchor.style.display = 'none';
  anchor.href = window.URL.createObjectURL(blob);
  anchor.setAttribute('download', filename);
  document.body.appendChild(anchor);

  // Trigger the download by simulating click
  anchor.click();

  // Clean up
  window.URL.revokeObjectURL(anchor.href);
  document.body.removeChild(anchor);
}

function downloadResource(url, filename) {
  fetch(url, {
    headers: new Headers({
      Origin: window.location.origin,
    }),
    mode: 'cors',
  })
    .then(response => response.blob())
    .then(blob => forceDownload(blob, filename))
    .catch(e => console.error(e));
}

downloadResource('https://memegen.link/xy/fetch/all_the_things.jpg?watermark=none');

This has a few limitations:

  • the file size limit of blobs is about 500MB
  • some websites will not allow for cross-origin requests, leading to errors like this one below

Failed to load https://example.com/example.jpg: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://example.com' is therefore not allowed access.

Ref 1: Leeroy in https://stackoverflow.com/a/49500465/1268612

Ref 2: https://davidwalsh.name/javascript-download

Full explanation: https://blog.logrocket.com/programmatic-file-downloads-in-the-browser-9a5186298d5c/

Karl Horky
  • 4,410
  • 2
  • 31
  • 35
  • this solution worked for me. tks very much. one small detail: i didn't need the filename parse from the url. i set the download attribute without the filename value and the name was inferred automatically. – João Melo Sep 01 '21 at 17:35
  • 1
    Great, thanks for the feedback and improvement @JoãoMelo! I've removed this part of the code. – Karl Horky Sep 02 '21 at 08:26