Easiest way to open a download window without navigating away from the page
What is the best cross browser way to open a download dialog (let’s assume we can set content-disposion:attachment in the headers) without navigating away from the current page, or opening popups, which doesn’t work well in Internet Explorer(IE) 6.
13 Answers 13
This javascript is nice that it doesn’t open a new window or tab.
This is the same as window.location = url; “Whenever a new value is assigned to the location object, a document will be loaded using the URL as if window.location.assign() had been called with the modified URL” — developer.mozilla.org/en-US/docs/Web/API/window.location
When using IE11 I found that this caused JS to stop. So for IE 11 I used window.open(url, ‘_blank’) which did open another tab, however that tab closed when it worked out the file was a download. This kept the JS running.
7 years have passed and I don’t know whether it works for IE6 or not, but this prompts OpenFileDialog in FF and Chrome.
var file_path = 'host/path/file.ext'; var a = document.createElement('A'); a.href = file_path; a.download = file_path.substr(file_path.lastIndexOf('/') + 1); document.body.appendChild(a); a.click(); document.body.removeChild(a);
@Manoj Rana — I have checked on FF 58.0.2 (64-bit) it is working. It won’t work on any FF if you remove 2 lines document.body.appendChild(a); document.body.removeChild(a);
To make it work on Edge 16 the header, from where the file comes, should contains Content-Type: application/octet-stream and Content-Disposition: attachment .
I know the question was asked 7 years and 9 months ago but many posted solutions doesn’t seem to work, for example using an works only with FireFox and doesn’t work with Chrome .
Best solution:
The best working solution to open a file download pop-up in JavaScript is to use a HTML link element, with no need to append the link element to the document.body as stated in other answers.
You can use the following function:
function downloadFile(filePath) < var link=document.createElement('a'); link.href = filePath; link.download = filePath.substr(filePath.lastIndexOf('/') + 1); link.click(); >
In my application, I am using it this way:
downloadFile('report/xls/myCustomReport.xlsx');
Working Demo:
function downloadFile(filePath) < var link = document.createElement('a'); link.href = filePath; link.download = filePath.substr(filePath.lastIndexOf('/') + 1); link.click(); >downloadFile("http://www.adobe.com/content/dam/Adobe/en/accessibility/pdfs/accessing-pdf-sr.pdf");
- You have to use the link.download attribute so the browser doesn’t open the file in a new tab and fires the download pop-up.
- This was tested with several file types (docx, xlsx, png, pdf, . ).
@Ctrl_Alt_Defeat Well in this case it won’t be easy to track the download process, but one trick can be to show this gif animation on the link click and hide it after a timeout, using this code: link.onclick = function() < document.body.innerText = "The file is being downloaded . "; setTimeout(function() < document.body.innerText = ""; >, 2000); > , you can see it working in this fiddle, but keep in mind that it’s not a recommended way to do it, it would be better handled if we were using Ajax .
Thanks @cнŝdk! I deleted my previous comment, as I found that there are other things that PWA breaks while on the way to document.createElement() . If I clean them up, the method still works.
I always add a target=»_blank» to the download link. This will open a new window, but as soon as the user clicks save, the new window is closed.
This is the best answer. In Internet Explorer, adding the ‘target=»_blank»‘ to a link that is to be downloadedwill stop the browser from navigating away (where «HTML1300: Navigation occurred» is printed), and thus can leave the page in an inconsistent state.
Put this in the HTML head section, setting the url var to the URL of the file to be downloaded:
Then put this in the body, which will start the download automatically after 5 seconds:
that doesnt work, because in IE6, if the user clicks «save» the file is saved, but the popup stays open. This is not acceptable.
This worked for me but I started getting weird glitchy behavior in my debug browser when I’d attempt to open multiple files (one after the other) somewhat rapidly.
I’ve been looking for a good way to use javascript to initiate the download of a file, just as this question suggests. However these answers not been helpful. I then did some xbrowser testing and have found that an iframe works best on all modern browsers IE>8.
downloadUrl = "http://example.com/download/file.zip"; var downloadFrame = document.createElement("iframe"); downloadFrame.setAttribute('src',downloadUrl); downloadFrame.setAttribute('class',"screenReaderText"); document.body.appendChild(downloadFrame);
class=»screenReaderText» is my class to style content that is present but not viewable.
same as .visuallyHidden in html5boilerplate
I prefer this to the javascript window.open method because if the link is broken the iframe method simply doesn’t do anything as opposed to redirecting to a blank page saying the file could not be opened.
window.open(downloadUrl, 'download_window', 'toolbar=0,location=no,directories=0,status=0,scrollbars=0,resizeable=0,width=1,height=1,top=0,left=0'); window.focus();
How to Save Files in JavaScript
In the web world, saving a file or “Save As” means downloading a file to the client’s machine. There isn’t a built-in method in JavaScript that allows us to do so. What we typically do (if we have a static file link) is add an anchor element in HTML and use the download attribute to make it downloadable. Something like this:
a href="/images/myFile.txt" download>
The problem is that we don’t always want the user to download when clicking on a link because we could have a bunch of logic before downloading or some dynamic data created without a static link. Let’s go through a few simple steps to create a saveAs function for downloading one or multiple files in JavaScript!
Unless we have static files available publicly on the server, we need to create content using a Blob , a file-like object in JavaScript.
Let’s create a function that will take some data as a parameter and return a new Blob text:
function createBlob(data) return new Blob([data], type: "text/plain" >); >
Of course, a Blob object has a lot more than just a plain text type. You can learn more in the official documentation.
Let’s look at two approaches for saving/downloading a file in JavaScript:
1. Use an Anchor element
We can dynamically create an anchor element in JavaScript using createElement and then programmatically invoke the click event. Here is a basic example:
const a = document.createElement("a"); a.click();
But to download a file, we need to pass it download and href attributes. The download will hold the file name and extension and the href will require a URL. Let’s create a function and put all the implementation together:
If we are using a static file with a relative path, all we need to do is this:
function saveAs() const a = document.createElement("a"); a.href = '/files/myFile.txt'; a.download = "myFile.txt"; a.click(); >
Download only works for same-origin URLs. Meaning, href can’t be a path different than your websites’ otherwise the behavior will change and it will redirect instead of downloading.
If the content is generated dynamically, we’ll need to create a blob and convert it to an object URL to make it downloadable. Also, we need to release the object at the very end when no longer needed:
function saveAs() const a = document.createElement("a"); const file = createBlob("Hello Blob!!"); const url = window.URL.createObjectURL(file); a.href = url; a.download = "myFile.txt"; a.click(); URL.revokeObjectURL(); >
Let’s improve the function to make it re-usable and have it support both options:
function saveAs(content, fileName) const a = document.createElement("a"); const isBlob = content.toString().indexOf("Blob") > -1; let url = content; if (isBlob) url = window.URL.createObjectURL(content); > a.href = url; a.download = fileName; a.click(); if (isBlob) window.URL.revokeObjectURL(url); > > // Consume the function as follows: const file = createBlob("Hello, file!"); saveAs(file, "myFile.txt");
2. Use file-saver library
FileSaver.js is a great solution to saving files on the client-side without having to write our own custom code.
First, we need to install the library:
const FileSaver = require('file-saver'); // Save Blob file const file = createBlob('Hello, file!'); FileSaver.saveAs(file, "myFile.txt"); // Save URL FileSaver.saveAs("https://httpbin.org/image", "image.jpg");
Zip and download multiple files
In certain cases, we need to download multiple files in one hit. Although this can be achieved by looping through the files and triggering the saveAs function, the user experience isn’t great and we’ll end up with so many files added to the download folder.
An alternative solution is to use JSZip, a library for creating, reading, and editing .zip files.
First, we need to install the library:
Then, we’ll create an async function that does the following logic:
const file1 = createBlob("Hello Blob 1!"); const file2 = createBlob("Hello Blob 2!");
const zip = new JSZip(); zip.file("file1.txt", file1); zip.file("file2.txt", file2);
- Generate the zip folder and as soon as it’s ready, we can call the saveAs function we did earlier:
const content = await zip.generateAsync( type: "blob" >); saveAs(content, "folder.zip");
Here is the full function:
async function zipFiles() const zip = new JSZip(); const file1 = createBlob("Hello, file 1!"); const file2 = createBlob("Hello, file 2!"); zip.file("file1.txt", file1); zip.file("file2.txt", file2); const content = await zip.generateAsync( type: "blob" >); saveAs(content, "folder.zip"); >
I hope you enjoyed learning from this article and if you have any questions, please leave a comment below.
Auto Pop Up Save As Window For Firefox
I’ve been using this code download PDF to directly download a link for pdf but this code only work in Google Chrome Can someone help me to make this work in Mozilla Firefox and IE8 as well. Because when I try to test it in Mozilla Firefox it opens the links but doesn’t pop up the «Save As» window.
Do you need it to be HTML5 or do you have server-side code you can hit? I usually use headers for my downloads
You want a Content-Disposition: attachment response header. You can also add a Download attribute on the A tag, which works in Firefox and Chrome but not IE.
@EricLaw I already tried putting a download attribute after the file path but still this only works for Google Chrome but in Mozilla Firefox it opens the link on same window
I don’t know what «after the filepath» means. Firefox 20+ is supposed to support the Download attribute, per caniuse.com/download Did you add the Content-Disposition: attachment header?
2 Answers 2
I’d use PHP headers so reference the file with something like this for the url:
Then use php to deliver the file:
//otherwise header('Content-type: application/pdf'); header('Content-Disposition: attachment; filename="myFile.pdf"'); readfile('myFile.pdf');
Note: pseudo code is not perfect 🙂
link window.URL = window.webkitURL || window.URL; var a = document.getElementById('save_data'); var data = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQImWNgYGBgAAAABQABh6FO1AAAAABJRU5ErkJggg=='; var filename = 'qqq.pdf'; a.download = filename; a.href = data; a.textContent = 'Downloading. '; //release memory a.onclick = function(e)< save_cleanup(this); >; //force click document.querySelector('#save_data').click(); function save_cleanup(a)< a.textContent = 'Downloaded'; setTimeout(function()< a.href = ''; var element = document.getElementById("save_data"); element.parentNode.removeChild(element); >, 1500); >;