How to save a base64 image to user's disk using JavaScript?

HTML5 download attribute

Just to allow user to download the image or other file you may use the HTML5 download attribute.

Static file download

<a href="/images/image-name.jpg" download>
<!-- OR -->
<a href="/images/image-name.jpg" download="new-image-name.jpg"> 

Dynamic file download

In cases requesting image dynamically it is possible to emulate such download.

If your image is already loaded and you have the base64 source then:

function saveBase64AsFile(base64, fileName) {
    var link = document.createElement("a");

    document.body.appendChild(link); // for Firefox

    link.setAttribute("href", base64);
    link.setAttribute("download", fileName);
    link.click();
}

Otherwise if image file is downloaded as Blob you can use FileReader to convert it to Base64:

function saveBlobAsFile(blob, fileName) {
    var reader = new FileReader();

    reader.onloadend = function () {    
        var base64 = reader.result ;
        var link = document.createElement("a");

        document.body.appendChild(link); // for Firefox

        link.setAttribute("href", base64);
        link.setAttribute("download", fileName);
        link.click();
    };

    reader.readAsDataURL(blob);
}

Firefox

The anchor tag you are creating also needs to be added to the DOM in Firefox, in order to be recognized for click events (Link).

IE is not supported: Caniuse link


In JavaScript you cannot have the direct access to the filesystem. However, you can make browser to pop up a dialog window allowing the user to pick the save location. In order to do this, use the replace method with your Base64String and replace "image/png" with "image/octet-stream":

"data:image/png;base64,iVBORw0KG...".replace("image/png", "image/octet-stream");

Also, W3C-compliant browsers provide 2 methods to work with base64-encoded and binary data:

  • atob()
  • btoa()

Probably, you will find them useful in a way...


Here is a refactored version of what I understand you need:

window.addEventListener('DOMContentLoaded', () => {
  const img = document.getElementById('embedImage');
  img.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA' +
    'AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO' +
    '9TXL0Y4OHwAAAABJRU5ErkJggg==';

  img.addEventListener('load', () => button.removeAttribute('disabled'));
  
  const button = document.getElementById('saveImage');
  button.addEventListener('click', () => {
    window.location.href = img.src.replace('image/png', 'image/octet-stream');
  });
});
<!DOCTYPE html>
<html>

<body>
  <img id="embedImage" alt="Red dot" />
  <button id="saveImage" disabled="disabled">save image</button>
</body>

</html>

This Works

function saveBase64AsFile(base64, fileName) {
    var link = document.createElement("a");
    document.body.appendChild(link);
    link.setAttribute("type", "hidden");
    link.href = "data:text/plain;base64," + base64;
    link.download = fileName;
    link.click();  
    document.body.removeChild(link);
}

Based on the answer above but with some changes