508

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.

Brett DeWoody
  • 50,328
  • 25
  • 121
  • 168
brentonstrine
  • 17,958
  • 23
  • 61
  • 112
  • 21
    Thanks to you "how to trigger a file download in javascript" would give answers much faster for any future searcher. – Danubian Sailor Mar 06 '14 at 17:07
  • 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. – Mark Amery Apr 05 '21 at 19:22

20 Answers20

511

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

MultiplyByZer0
  • 4,341
  • 3
  • 27
  • 46
Joe Pigott
  • 6,505
  • 5
  • 28
  • 42
  • 39
    Not Work With Safari and certain IE versions – Mohamed Hussain Jul 18 '16 at 05:47
  • 1
    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. – sgsvnk Jul 18 '16 at 12:51
  • @AlexeyFShevelyov The link for caniuse is already in the post – Joe Pigott Oct 07 '16 at 16:03
  • 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. – Ben Nov 04 '16 at 11:45
  • 7
    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. – MK10 Jan 16 '17 at 14:05
  • 12
    How can this be applied to a *button* object instead of just an *a tag*? – storm_m2138 Mar 29 '17 at 22:00
  • 9
    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 solution – Akshat Gupta Aug 28 '17 at 11:38
  • 1
    @storm_m2138 you just wrap your button inside the a.. – Kaylined Apr 13 '18 at 17:31
  • 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 https – Jonny Dec 01 '18 at 17:51
  • 7
    The question is explicitly asking to use a button instead of a link – Quentin Jul 01 '19 at 13:15
  • 1
    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. – K.S Sep 16 '19 at 06:08
  • 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. – Zia Ul Rehman Mughal Dec 03 '19 at 05:15
312

For the button you can do

<form method="get" action="file.doc">
   <button type="submit">Download!</button>
</form>
Gray
  • 108,756
  • 21
  • 270
  • 333
Cfreak
  • 18,362
  • 6
  • 44
  • 56
  • 1
    You can save the form tag and just add an onclick to the button tag. – Florian Leitgeb Jan 23 '15 at 13:10
  • You could always style the anchor tag like a button! – mix3d Sep 24 '15 at 17:11
  • 15
    doesn't work as a trigger, just redirect to the url as 'a' tag. – fdrv Apr 05 '16 at 15:02
  • 13
    This works better : Download – kscius Jul 07 '16 at 03:33
  • 14
    @kscius 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. – Cfreak Jul 07 '16 at 03:40
  • 2
    what's the difference between having an anchor with button styling and having a form with a button? – Andrei Epure is hiring Feb 23 '17 at 09:52
  • @aepure the OP wanted to know how to do it with a form button. – Cfreak Feb 23 '17 at 22:59
  • 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. – Mark Amery Apr 05 '21 at 19:25
101

HTML:

<button type="submit" onclick="window.open('file.doc')">Download!</button>
Ani Menon
  • 23,084
  • 13
  • 81
  • 107
sleepyup
  • 1,091
  • 1
  • 7
  • 2
  • 4
    What if i wanna download a xml file? – g07kore May 12 '15 at 20:07
  • 2
    Thanks for your code. I have tested, it can working in IE, Chrome, Firefox. – muthukumar Sep 22 '16 at 09:11
  • 9
    If you have a file acceptable by the browser like a PDF it will open in new tab instead to show download dialog. – WindRider Jan 25 '17 at 18:07
  • 3
    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. – Elendurwen Dec 06 '18 at 14:14
  • 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. – Mark Amery Apr 05 '21 at 19:31
  • This won't work with base64 types as most data types are blocked nowadays. – Andrew Apr 06 '21 at 17:58
71

With jQuery:

$("#fileRequest").click(function() {
    // hope the server sets Content-Disposition: attachment!
    window.location = 'file.doc';
});
Mark Amery
  • 110,735
  • 57
  • 354
  • 402
Matt Ball
  • 332,322
  • 92
  • 617
  • 683
  • 2
    Perfect, thanks. Do you happen to know if most servers will set the Content-Disposition to 'attachment' by default? – brentonstrine Jul 23 '12 at 21:38
  • 7
    There is no "most." It completely depends. Don't rely on it being set. – Matt Ball Jul 23 '12 at 21:43
  • 3
    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: – user124384 Jul 24 '15 at 15:08
  • 3
    No jquery. Period. – Adam Arold Apr 01 '18 at 22:17
  • 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](https://stackoverflow.com/q/18097057/673991) benign. – Bob Stein Jun 05 '18 at 15:56
  • 2
    This doest work if you're trying to download an image, it would open the image in the browser – Dheeraj Aug 12 '19 at 12:45
  • @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? – rileymcdowell Feb 27 '21 at 16:40
  • 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. – Mark Amery Apr 05 '21 at 19:32
57

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)
}
Mark Amery
  • 110,735
  • 57
  • 354
  • 402
Stefanos Chrs
  • 1,257
  • 2
  • 13
  • 42
24

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";
}
Danubian Sailor
  • 21,505
  • 37
  • 137
  • 211
  • It does, at least if you actually apprnf the iframe to document.body. – yxhuvud May 27 '16 at 08:01
  • 1
    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. – Dobes Vandermeer Oct 21 '16 at 18:08
  • Works in Chrome as of Version 61.0.3163.100 (Official Build) (64-bit) – AndrewBenjamin Sep 25 '17 at 18:51
  • Does not work with images in Firefox v57. It just renders the image in the iframe. – Antony Nov 21 '17 at 22:31
  • 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). – Mark Amery Apr 05 '21 at 19:42
17

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.

georgeawg
  • 46,994
  • 13
  • 63
  • 85
Apps-n-Add-Ons
  • 1,779
  • 1
  • 16
  • 26
11

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);
}
Delconis
  • 265
  • 2
  • 9
  • on 404 -> page change to a 404 error page. same problem as stated on the other `location.href` solutions. – BananaAcid Aug 18 '19 at 13:19
  • 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. – Mark Amery Apr 05 '21 at 19:44
10

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>
Starwarswii
  • 1,335
  • 12
  • 13
8

What about:

<input type="button" value="Download Now!" onclick="window.location = 'file.doc';">
John Weisz
  • 23,615
  • 9
  • 74
  • 118
olli
  • 1,596
  • 3
  • 18
  • 36
  • 7
    This does not work, if your file, for example, is an image, since it would just be opened in the browser. – Juggernaut Feb 02 '18 at 14:47
  • Another issue occurs which is if the file is missing it navigates the entire page to a 404 page – Hugheth Jul 10 '18 at 07:48
  • 1
    It works perfectly in 2020 (for every file), and it is the simplest solution of all. Amazing! – NickDimou Jan 07 '21 at 21:23
  • 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. – Mark Amery Apr 05 '21 at 19:44
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>
David Willhite
  • 115
  • 1
  • 4
  • 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. – Mark Amery Apr 05 '21 at 19:45
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();">
slayernoah
  • 3,714
  • 10
  • 37
  • 65
  • 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? – Andrei Epure is hiring Feb 23 '17 at 09:48
  • 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. – Mark Amery Apr 05 '21 at 19:48
1

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!

John Weisz
  • 23,615
  • 9
  • 74
  • 118
Ronaldo
  • 79
  • 2
  • 1
    For Chrome it is a great solution – Hayk Aramyan Jun 15 '16 at 08:13
  • 1
    Doesn't work in Safari either: [W3 Schools](http://www.w3schools.com/tags/att_a_download.asp) – Alex Aug 08 '16 at 09:33
  • 2
    Not working in the MS browsers is a rather big problem and Chrome is not always going to be the answer. – SudoKid Jan 08 '17 at 20:11
  • 1
    You can't put a link inside a button in HTML – Quentin Jul 01 '19 at 13:14
  • Not legal HTML; https://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. – Mark Amery Apr 05 '21 at 19:50
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

Mark Amery
  • 110,735
  • 57
  • 354
  • 402
Gleb Dolzikov
  • 556
  • 5
  • 10
1

In my original answer, I offered a work around that does not work any longer: If the file to be downloaded is not on the same server, the attribute download does not work. The problem is that the attribute download does only work when the file to be downloaded is on the same server of the tab. Others have faced this problem too and the problem is extensively covered at Chrome Download Attribute not working.

Original answer:

There is a difference between loading a file and downloading a file. The following html code loads a file:

<a href="http://www.fbi.gov/top-secret.pdf">loading on the same tab</a>

After clicking on this link, your current tab will be replaced with the pdf-file that can then be downloaded. On right-clicking on this link, you can choose the menu item save link as for downloading the file directly. If you wish to obtain a save as dialog on clicking on such a link, you might want to take the following code:

<a href="http://www.fbi.gov/top-secret.pdf?download=1">save as...</a>

Your browser will download this file immediately if you choose to use a download directory in your options. Otherwise, your browser will be offering a save as-dialog.

You can also choose a button for downloading:

<button type="submit" onclick="window.open('http://www.fbi.gov/top-secret.pdf?download=1')">
    save as...
</button>

If you wish to load the link on a new tab, you take

<a href="http://www.fbi.gov/top-secret.pdf" target="_blank">loading on a new tab</a>

A form element does not heed the directive ?download=1. It only heeds the directive target="_blank":

<form method="get" action="http://www.fbi.gov/top-secret.pdf" target="_blank">
    <button type="submit">loading on a new tab</button>
</form>
Reimer
  • 77
  • 6
  • This is wrong; using `?download=1` doesn't work. There's no magic browser behaviour that looks for `download=1` in a query string and infers that it needs to download the file. – Mark Amery Apr 05 '21 at 19:53
  • @MarkAmery you are right: I offered a work around that does not work any longer; I commented on this in my edit – Reimer Apr 07 '21 at 10:24
0
<a href="file.doc"><button>Download!</button></a>

One of the simplest way for button and the text-decoration will help to alter or to remove the text decoration of the link.

iamabdm
  • 329
  • 1
  • 9
-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

BananaAcid
  • 2,608
  • 28
  • 34
Bellash
  • 5,719
  • 3
  • 39
  • 72
-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.

-7

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.

Brana
  • 1,087
  • 2
  • 15
  • 34
-9

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>
John Weisz
  • 23,615
  • 9
  • 74
  • 118
Mark
  • 1
  • 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. – Rocket Hazmat Jul 23 '12 at 21:28
  • @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 - – Mark Jul 23 '12 at 21:33
  • The question is explicitly asking how to do this with a button instead of a link. – Quentin Jul 01 '19 at 13:14
  • the download attribute is missing in this solution. Even after adding download attributes it will not work for cross-domain. – s sharif Nov 07 '19 at 07:44