2

I have a requirement to get the file from an API which is returning filedata in base64 format. I am adding that to <a href tag that looks like below

<a id="myFile" href="data:image/png;base64,..." click="downloadFile()">Download File</a>

So I want to trigger filedownload using $('#myFile').click() which is going to downloadFile() function, but I can't use location.href as I don't want the page to be redirected.

Is there any alternative for this requirement? Any suggestions would be a great help.

NOTE: I am getting href value dynamically with some ajax response once the link is clicked, initially href is set to # and will be replaced with appropriate downloadable string as above. I want to trigger file download along with the same event that triggered ajax request and not with a separate click event.

Sridhar Gudimela
  • 564
  • 8
  • 14
  • Limited browser support. Here is a Chrome only solution. http://stackoverflow.com/a/15832662/5496966 .. You could also replace the application type from `data:image/png` to `data:application/octet-stream` .. it forces the browser to download instead of navigating to the href value. – AA2992 Sep 03 '16 at 04:11
  • Also that may download a bin file. You will have to give it a name and a filetype with whatever method you go with. – AA2992 Sep 03 '16 at 04:19
  • Awsome Ankith. This really worked. Is there anyway to make it multibrowser. Just mention it in regular answer, will mark it right. Thank you for your help. – Sridhar Gudimela Sep 03 '16 at 15:30
  • Think you should switch out manually to automatically in your title. Manually means user must click on the link to save it – Endless Sep 04 '16 at 00:26

3 Answers3

4

Just create, click and delete a new link in the DOM after the ajax request is complete. Should work.

Here is a link to a JS fiddle example.

// execute this after the ajax request is complete

var myFile = document.getElementById('myFile');
var dataURI = myFile.getAttribute('href');

myFile.addEventListener("click", function(event){
  event.preventDefault();
  // check if href value exists
  if(dataURI.length) {
    var fileName = 'image.png';
    var link = document.createElement("a");
    link.setAttribute("href", dataURI);
    link.setAttribute("download", fileName);    
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
    delete link;
  }
});

Note: Browsers may not support the filename set in download attribute if there are Cross Origin Requests.

AA2992
  • 1,559
  • 3
  • 17
  • 23
3

You can just use the download attribute - no JS required.

<a id="myFile" href="data:image/png;base64,..." download>Download File</a>

https://developer.mozilla.org/en/docs/Web/HTML/Element/a#attr-download

Mitya
  • 33,629
  • 9
  • 60
  • 107
  • This is not what I am looking at. I added a note to my initial request. My actual request is to download the file with an ajax request. Ajax request ad Download file should happen at the same click event. – Sridhar Gudimela Sep 02 '16 at 20:55
  • I still think you should add the download attribute (with a name also) and when the link's href has been created call `myFile.click()` to download it automatically when the ajax is done – Endless Sep 04 '16 at 00:18
  • The initial value is `#` so on click the page reloads, which is not what he wants. He has a script set to change the href value on the first click, which creates a need to preventdefault .. So he cannot use the download attribute. – AA2992 Sep 04 '16 at 01:10
  • Also download is a HTML5 tag which will not work for many of the older versions. – Sridhar Gudimela Sep 04 '16 at 04:49
  • I'm gonna say that in modern frameworks, this is a far cleaner approach. In Angular I had a similar challenge and this was all it took: – TomDK Jun 01 '23 at 08:19
2

If you include FileSaver in your page then you can do something like

fetch(url).then(res => res.blob()).then(blob => saveAs(blob, 'filename.txt'))
Endless
  • 34,080
  • 13
  • 108
  • 131