How to trigger a file download when clicking an HTML button or JavaScript
Asked Answered
C

25

679

This is crazy but I don't know how to do this, and because of how common the words are, it's hard to find what I need on search engines. I'm thinking this should be an easy one to answer.

I want a simple file download, that would do the same as this:

<a href="file.doc">Download!</a>

But I want to use an HTML button, e.g. either of these:

<input type="button" value="Download!">
<button>Download!</button>

Likewise, is it possible to trigger a simple download via JavaScript?

$("#fileRequest").click(function(){ /* code to download? */ });

I'm definitely not looking for a way to create an anchor that looks like a button, use any back-end scripts, or mess with server headers or mime types.

Citronella answered 23/7, 2012 at 21:22 Comment(2)
Thanks to you "how to trigger a file download in javascript" would give answers much faster for any future searcher.Sideways
Your restrictions in your final paragraph don't make much sense to me. If you're open to answers that use JavaScript (since you say so) or that require changing the DOM structure (like the one you've accepted), why not also an anchor styled as a button? I can't imagine a scenario where the first two would be fine but the anchor as a button would be problematic.Capella
C
343

For the button you can do

<form method="get" action="file.doc">
   <button type="submit">Download!</button>
</form>
Cornerstone answered 23/7, 2012 at 21:26 Comment(8)
You can save the form tag and just add an onclick to the button tag.Incorporating
You could always style the anchor tag like a button!Sprague
doesn't work as a trigger, just redirect to the url as 'a' tag.Spermatozoid
This works better : <a href="path_to_file" download="proposed_file_name">Download</a>Petrina
@Petrina even today the download attribute is not supported in IE 11 (it is now supported in Edge) and it is not supported in Safari. In 2012 when the answer was originally posted it wasn't supported in any major browser.Cornerstone
what's the difference between having an anchor with button styling and having a form with a button?Carriecarrier
@aepure the OP wanted to know how to do it with a form button.Cornerstone
This doesn't necessarily trigger a download. It simply causes the browser to navigate to file.doc. Whether that results in file.doc being downloaded or being shown as a page in the browser depends upon the headers returned by the server when it serves file.doc and on what file types the browser is capable of rendering.Capella
P
665

You can trigger a download with the HTML5 download attribute.

<a href="path_to_file" download="proposed_file_name">Download</a>

Where:

  • path_to_file is a path that resolves to an URL on the same origin. That means the page and the file must share the same domain, subdomain, protocol (HTTP vs. HTTPS), and port (if specified). Exceptions are blob: and data: (which always work), and file: (which never works).
  • proposed_file_name is the filename to save to. If it is blank, the browser defaults to the file's name.

Documentation: MDN, HTML Standard on downloading, HTML Standard on download, CanIUse

Pseudohermaphrodite answered 7/9, 2013 at 22:54 Comment(14)
Not Work With Safari and certain IE versionsStake
Is there any javascript work around to achieve the same functionality? Remaining answers, don't replicate the same feature. They either open a new window or relocate to different url.Fahy
@AlexeyFShevelyov The link for caniuse is already in the postPseudohermaphrodite
Nice. Being able to rename the file on download is a brilliant feature. Wish it would work in Safari though, seems it's supported in the next version though according to caniuse.Lulualaba
Using a combination of download and target="_blank" seems to be sufficient to cover most use cases. Browsers that understand download treat it as a download, otherwise it's opened in a new tab.Equiprobable
How can this be applied to a button object instead of just an a tag?Laverty
Actually this only works for urls of the same origin as mentioned in the MDN docs. This is a huge limitation if we are looking to develop a generic solutionCytokinesis
@Laverty you just wrap your button inside the a.. <a href="path_to_file" download="proposed_file_name"><button type=button">My Button</button></a>Edict
Furthermore you will get this console output when the href link is 'https': 'The download attribute was ignored because its href attribute has a different url security' even tough the page you are downloading from is also running on httpsSexagenarian
The question is explicitly asking to use a button instead of a linkOm
hi, this above solution is not what I need, it is opening file or image in new tab but I directly want to download file.Radioactive
It worked for same origin files. but when files were on S3 and i had a signed url returned from server, it is just opening the file in a pdf viewer in same tab.Basuto
what if the file that needs to be downloaded is stored in your project folder? How do we download it then? we won't have a url in that case. ...Vallejo
thank you very much after 9 years this is still helpRoslyn
C
343

For the button you can do

<form method="get" action="file.doc">
   <button type="submit">Download!</button>
</form>
Cornerstone answered 23/7, 2012 at 21:26 Comment(8)
You can save the form tag and just add an onclick to the button tag.Incorporating
You could always style the anchor tag like a button!Sprague
doesn't work as a trigger, just redirect to the url as 'a' tag.Spermatozoid
This works better : <a href="path_to_file" download="proposed_file_name">Download</a>Petrina
@Petrina even today the download attribute is not supported in IE 11 (it is now supported in Edge) and it is not supported in Safari. In 2012 when the answer was originally posted it wasn't supported in any major browser.Cornerstone
what's the difference between having an anchor with button styling and having a form with a button?Carriecarrier
@aepure the OP wanted to know how to do it with a form button.Cornerstone
This doesn't necessarily trigger a download. It simply causes the browser to navigate to file.doc. Whether that results in file.doc being downloaded or being shown as a page in the browser depends upon the headers returned by the server when it serves file.doc and on what file types the browser is capable of rendering.Capella
G
152

A simple JS solution:

function download(url) {
  const a = document.createElement('a')
  a.href = url
  a.download = url.split('/').pop()
  document.body.appendChild(a)
  a.click()
  document.body.removeChild(a)
}
Gogol answered 19/4, 2018 at 9:8 Comment(16)
@NicholasKyriakides Kind of reminds me of this gem: image.ibb.co/dtkUWJ/Selection_002.pngGogol
@BryanLarsen what version of FF?Gogol
@BryanLarsen You are right, Firefox doesn't allow this without adding the element to body first. Thank you, updating the answerGogol
Is there a way that javascript function be triggered once the download finishes? Just trying to show a message once downloads start and remove the message once download completes.Communication
@mohitbansal (un)fortunately no as it's in the browser levelGogol
This works on Firefox and Chrome for me, but on Edge it doesn't work.Giess
I just want to know where should i add the file path?Thisbee
@NarenVerma href is the file url and download is the name of the downloaded fileGogol
Do I need to add like this href="file path"; download="filename";? or it will fetch from <a href="file.doc">Download!</a>? Can you share or update or any jsfiddle link with full code?Thisbee
You can just copy paste the above inside your function and replace the a.href = item.url with a.href = 'file path' and a.download = item.url.split('/').pop() with a.download = 'filename' and that's it :)Gogol
This is best solution out here and should be accepted answer.Paregoric
Can someone tell me why it opens the file (pdf in my case) in a new tab and doesn't actually download it?Scrivener
Hello @Scrivener this depends on the browser settings. On Chrome, you go to Settings > Privacy > Site Settings > PDF Documents you can select to download instead of preview.Gogol
@StefanosChrs are you sure about this? your code works fine using base64 string instead of url as href.Erinaceous
@Erinaceous if you want to download a base64 string then you need to first convert it to a Blob url.Gogol
@Erinaceous check out a sample implementation here jsfiddle.net/stefanoschrs/zd4e7g6qGogol
P
125

HTML:

<button type="submit" onclick="window.open('file.doc')">Download!</button>
Prochora answered 7/9, 2013 at 18:57 Comment(6)
What if i wanna download a xml file?Careless
Thanks for your code. I have tested, it can working in IE, Chrome, Firefox.Newman
If you have a file acceptable by the browser like a PDF it will open in new tab instead to show download dialog.Lifeline
window.open can trigger popup-blocking in a browser and is thus not recommended. You could use window.location = 'path' , although that would go to the location in the same browser window.Exarch
This doesn't necessarily trigger a download. It simply causes the browser to navigate to file.doc. Whether that results in file.doc being downloaded or being shown as a page in the browser depends upon the headers returned by the server when it serves file.doc and on what file types the browser is capable of rendering.Capella
This won't work with base64 types as most data types are blocked nowadays.Viceregent
A
75

With jQuery:

$("#fileRequest").click(function() {
    // hope the server sets Content-Disposition: attachment!
    window.location = 'file.doc';
});
Audy answered 23/7, 2012 at 21:23 Comment(8)
Perfect, thanks. Do you happen to know if most servers will set the Content-Disposition to 'attachment' by default?Citronella
There is no "most." It completely depends. Don't rely on it being set.Audy
This issue has been driving me ballistic, and this was the only option that worked (and is supported by IE). I'll add for any n00bs like me that to set the Content-Disposition, all you have to do is: <?php header('Content-Disposition: attachment; filename="filename.here"'); ?>Eanore
No jquery. Period.Weathercock
Even with proper Content-Disposition, Chrome gives a warning: Resource interpreted as Document but transferred with MIME type application/pdf or whatever the Content-Type is. It is apparently benign.Bravado
This doest work if you're trying to download an image, it would open the image in the browserSama
@AdamArold Unless I missed something, jquery solutions are acceptable for OP. For example, OP used jquery in their sample code. What is the reason for your comment?Frosty
As alluded to in the code comment, this doesn't necessarily trigger a download. It simply causes the browser to navigate to file.doc. Whether that results in file.doc being downloaded or being shown as a page in the browser depends upon the headers returned by the server when it serves file.doc and on what file types the browser is capable of rendering.Capella
S
27

You can do it with "trick" with invisible iframe. When you set "src" to it, browser reacts as if you would click a link with the same "href". As opposite to solution with form, it enables you to embed additional logic, for example activating download after timeout, when some conditions are met etc.

It is also very silient, there's no blinking new window/tab like when using window.open.

HTML:

<iframe id="invisible" style="display:none;"></iframe>

Javascript:

function download() {
    var iframe = document.getElementById('invisible');
    iframe.src = "file.doc";
}
Sideways answered 6/3, 2014 at 16:57 Comment(5)
It does, at least if you actually apprnf the iframe to document.body.Trapezium
This doesn't seem to be working in Chrome right now, although it used to work. I wonder if it kind of intermittently stops working in different versions of Chrome.Bowers
Works in Chrome as of Version 61.0.3163.100 (Official Build) (64-bit)Bellbottoms
Does not work with images in Firefox v57. It just renders the image in the iframe.Choroid
This will fail silently if the file is of a type the browser knows how to render itself, though (unless the server returns a Content-Disposition header indicating the file should be downloaded).Capella
D
20

Bootstrap Version

<a class="btn btn-danger" role="button" href="path_to_file"
   download="proposed_file_name">
  Download
</a>

Documented in Bootstrap 4 docs, and works in Bootstrap 3 as well.

Delubrum answered 8/4, 2018 at 19:34 Comment(4)
The only thing this has to do with Bootstrap is the class names, it's just the power of HTML5.Gaivn
The question is explicitly asking how to do this with a button instead of a link.Om
if you knew anything at all about bootstrap, you would see that it IS a button.Ambur
The button tag didn't work for me. But this one did.Cymatium
A
19

I think this is the solution you were looking for

<button type="submit" onclick="window.location.href='file.doc'">Download!</button>

I hade a case where my Javascript generated a CSV file. Since there is no remote URL to download it I use the following implementation.

downloadCSV: function(data){
    var MIME_TYPE = "text/csv";

    var blob = new Blob([data], {type: MIME_TYPE});
    window.location.href = window.URL.createObjectURL(blob);
}
Alinealinna answered 22/3, 2017 at 19:28 Comment(2)
on 404 -> page change to a 404 error page. same problem as stated on the other location.href solutions.Diploblastic
This (at least the first implementation) doesn't necessarily trigger a download. It simply causes the browser to navigate to file.doc. Whether that results in file.doc being downloaded or being shown as a page in the browser depends upon the headers returned by the server when it serves file.doc and on what file types the browser is capable of rendering.Capella
A
12

You can hide the download link and make the button click it.

<button onclick="document.getElementById('link').click()">Download!</button>
<a id="link" href="file.doc" download hidden></a>
Allegra answered 9/6, 2017 at 17:28 Comment(2)
For this to work in Firefox, the resource has to be on the same domain as the document. Setting CORS headers does not help.Choroid
Don't ever do thisSepoy
S
8

What about:

<input type="button" value="Download Now!" onclick="window.location = 'file.doc';">
Strict answered 22/7, 2013 at 3:23 Comment(4)
This does not work, if your file, for example, is an image, since it would just be opened in the browser.Palladian
Another issue occurs which is if the file is missing it navigates the entire page to a 404 pageHarilda
It works perfectly in 2020 (for every file), and it is the simplest solution of all. Amazing!Legg
This doesn't necessarily trigger a download. It simply causes the browser to navigate to file.doc. Whether that results in file.doc being downloaded or being shown as a page in the browser depends upon the headers returned by the server when it serves file.doc and on what file types the browser is capable of rendering.Capella
A
6

In my testing the following works for all file types and browsers as long as you use a relative link:

<a href="/assets/hello.txt" download="my_file.txt"><button>Download 2</button></a>
  • /assets/hello.txt is just a relative path on my site. Change it to your own relative path.
  • my_file.txt is the name you want the file to be called when it is downloaded.

Explanation

I noticed there were comments under a lot of the answers that said the browser would just try to open the file itself rather than downloading it depending on the file type. I discovered this to be true.

I made two buttons to test it out using two different methods:

enter image description here

<button onclick="window.location.href='/assets/hello.txt';">Download 1</button>

<a href="/assets/hello.txt" download="my_file.txt"><button>Download 2</button></a>

Notes:

  • Button 1 opened the text file in a new browser tab. However, Button 1 would download the file for file types that it couldn't open itself (for example, .apk files).
  • Button 2 downloaded the text file. However, Button 2 only downloaded the file if the path was relative. When I changed the path to an absolute path, then the browser opened it in a new tab.

I tested this on Firefox, Safari, and Chrome.

Auricula answered 3/7, 2021 at 7:17 Comment(0)
C
4

Hello I just include the word 'download' and works well.

<a href="file.pdf" download>Download</a>

So in javascript you can use the follow:

function onStartedDownload(id) {
  console.log(`Started downloading: ${id}`);
}

function onFailed(error) {
  console.log(`Download failed: ${error}`);
}

var downloadUrl = "https://example.org/image.png";

var downloading = browser.downloads.download({
  url : downloadUrl,
  filename : 'my-image-again.png',
  conflictAction : 'uniquify'
});

downloading.then(onStartedDownload, onFailed);
Cirrus answered 29/7, 2021 at 17:51 Comment(1)
Uncaught ReferenceError: browser is not definedCauseway
K
4

all you need to do is add Download after the file name which you have entered:

Before:

<a href="file.doc">Download!</a>

After

<a href="" Download="file.doc" >Download!</a>

Make sure the download is written with a capital letter otherwise it's not gonna work.

Kaolack answered 23/1, 2022 at 0:13 Comment(0)
R
3

If your looking for a vanilla JavaScript (no jQuery) solution and without using the HTML5 attribute you could try this.

const download = document.getElementById("fileRequest");

download.addEventListener('click', request);

function request() {
    window.location = 'document.docx';
}
.dwnld-cta {
    border-radius: 15px 15px;
    width: 100px;
    line-height: 22px
}
<h1>Download File</h1>
<button id="fileRequest" class="dwnld-cta">Download</button>
Rigobertorigor answered 5/2, 2018 at 21:38 Comment(1)
This doesn't necessarily trigger a download. It simply causes the browser to navigate to file.doc. Whether that results in file.doc being downloaded or being shown as a page in the browser depends upon the headers returned by the server when it serves file.doc and on what file types the browser is capable of rendering.Capella
B
3

<a href="file.doc"><button>Download!</button></a>
This will download the file as .doc file extension is not supported to be opened in browser.
One of the simplest way for button and the text-decoration will help to alter or to remove the text decoration of the link.

Bronchitis answered 23/4, 2021 at 9:48 Comment(3)
Simplest solution ever.Twyla
The simplest yet wrong. According to HTML Living Standard html.spec.whatwg.org/multipage/… a element can't have interactive elements as descendants and button element is an interactive one.Highlander
@Highlander Indeed you are correct, but I believe that the answer satisfies the requirements of the main question.Bronchitis
G
2

Anywhere between your <body> and </body> tags, put in a button using the below code:

<button>
    <a href="file.doc" download>Click to Download!</a>
</button>

This is sure to work!

Graff answered 25/5, 2016 at 17:12 Comment(5)
For Chrome it is a great solutionLurette
Doesn't work in Safari either: W3 SchoolsStupidity
Not working in the MS browsers is a rather big problem and Chrome is not always going to be the answer.Septate
You can't put a link inside a button in HTMLOm
Not legal HTML; validator.w3.org/nu complains that "The element a must not appear as a descendant of the button element." Seems to render nonetheless in the browsers I've tried, but all the same, I wouldn't risk it.Capella
O
2

If you want

<a href="path_to_file" download="proposed_file_name">Download</a>

for the ability to download files that would be rendered by the browser otherwise, But still want a neat javascript function to use in a button; you can have an invisible link in html and click it in javascript.

function download_file() {
  document.getElementById("my_download").click()
}
<a id="my_download" href="path_to_file" download="file_name" style="display:none;"></a>

<button onClick="download_file()">Download!!!</button>
Orsola answered 10/1, 2022 at 15:44 Comment(0)
D
1

This is what finally worked for me since the file to be downloaded was determined when the page is loaded.

JS to update the form's action attribute:

function setFormAction() {
    document.getElementById("myDownloadButtonForm").action = //some code to get the filename;
}

Calling JS to update the form's action attribute:

<body onLoad="setFormAction();">

Form tag with the submit button:

<form method="get" id="myDownloadButtonForm" action="">
    Click to open document:  
    <button type="submit">Open Document</button>
</form>

The following did NOT work:

<form method="get" id="myDownloadButtonForm" action="javascript:someFunctionToReturnFileName();">
Distiller answered 19/11, 2015 at 23:1 Comment(2)
probably because if you have the file at load time, can't you just render the action on the server using a templating engine? why the need for js code?Carriecarrier
Like other solutions here that use a default form action, this doesn't necessarily trigger a download. It simply causes the browser to navigate to the target URL. Whether that results in the file at that URL being downloaded or being shown as a page in the browser depends upon the headers returned by the server when it serves the file and on what file types the browser is capable of rendering.Capella
H
1

If you can't use form, another approach with downloadjs fit nice. Downloadjs use blob and html 5 file API under the hood:

<div onClick=(()=>{downloadjs(url, filename)})/>

*it's jsx/react syntax, but can be used in pure html

Holifield answered 7/8, 2017 at 12:55 Comment(2)
To avoid CORS problems for images on other domains, put crossorigin="anonymous" into the img tag, like this: <img src="image.png" crossorigin="anonymous" />Orton
I had a button that would download an in-memory string as a file. This worked, no problems. Thanks.Keelung
M
1

Not really an answer to the original question but it may help others which face similar situations as myself.

If the file you want to download is not hosted on the same origin but you want to be able to download it, you can do that with the Content-Disposition header. Make sure the server includes the header when responding to requests of the file.

Setting a value like Content-Disposition: attachment will ensure that the file will be downloaded instead of viewed in the browser.

A simple <a href="http://www.notMyOrigin.com/file.txt">Download</a> pointing to your file should download it in this case.

Monotony answered 2/12, 2021 at 14:46 Comment(0)
C
0

You can use the HTML download attribute to specify that the target will be downloaded when a user clicks on the hyperlink.

<a href="https://www.w3schools.com/images/myw3schoolsimage.jpg" download>
  <img src="https://www.w3schools.com/images/myw3schoolsimage.jpg" alt="W3Schools">
</a>
Circumspection answered 25/1 at 7:18 Comment(0)
S
-1

Another way of doing in case you have a complex URL such as file.doc?foo=bar&jon=doe is to add hidden field inside the form

<form method="get" action="file.doc">
  <input type="hidden" name="foo" value="bar" />
  <input type="hidden" name="john" value="doe" />
  <button type="submit">Download Now</button>
</form>

inspired on @Cfreak answer which is not complete

Selfforgetful answered 22/6, 2017 at 10:21 Comment(0)
R
-1

The solution I have come up with is that you can use download attribute in anchor tag but it will only work if your html file is on the server. but you may have a question like while designing a simple html page how can we check that for that you can use VS code live server or bracket live server and you will see your download attribute will work but if you will try to open it simply by just double clicking html page it open the file instead of downloading it. conclusion: attribute download in anchor tag only works if your html file is no server.

Rebellion answered 27/10, 2020 at 5:58 Comment(0)
N
-9

For me ading button instead of anchor text works really well.

<a href="file.doc"><button>Download!</button></a>

It might not be ok by most rules, but it looks pretty good.

Nigrosine answered 27/8, 2017 at 6:8 Comment(3)
This only works because your browser doesn't support .doc files.Sacrilege
Your HTML is invalid. <a> elements may not contain <button> elements.Om
was it always that way though? This answer was two years old when you commented that.Ambur
M
-10

If you use the <a> tag, do not forget to use the entire url which leads to the file -- i.e.:

<a href="http://www.example.com/folder1/file.doc">Download</a>
Mansized answered 23/7, 2012 at 21:27 Comment(4)
I don't think that's the problem here. Also the "absolute" path isn't needed if the link is in the same path as the file.Ascent
@Rocket - you are, of course, correct about the absolute path, however, it is the best way to make certain to get it right. I will leave it to the OP to decide if it was helpful -Mansized
The question is explicitly asking how to do this with a button instead of a link.Om
the download attribute is missing in this solution. Even after adding download attributes it will not work for cross-domain.Fitch

© 2022 - 2024 — McMap. All rights reserved.