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

136,769

Solution 1

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

Solution 2

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:

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>

Solution 3

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

Share:
136,769
vengatesh
Author by

vengatesh

i am a die hard fan of flex , i have been working with flex since 2010. and i would like to share my knowledge and experience , and also awaiting to get more knowledge.

Updated on June 12, 2021

Comments

  • vengatesh
    vengatesh almost 3 years

    I have converted the source content from the <img> html tag to a base64String using JavaScript. The image was displayed clearly. Now I want to save that image to user's disk using javascript.

    <html>
        <head>
        <script>
            function saveImageAs () {
                var imgOrURL;
                embedImage.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA" +
                                 "AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO" +
                                 "9TXL0Y4OHwAAAABJRU5ErkJggg==";
                imgOrURL = embedImage;
                if (typeof imgOrURL == 'object')
                    imgOrURL = embedImage.src;
                window.win = open(imgOrURL);
                setTimeout('win.document.execCommand("SaveAs")', 0);
            }
        </script>
        </head>
        <body>
            <a href="#" ONCLICK="saveImageAs(); return false" >save image</a>
    
            <img id="embedImage" alt="Red dot">
        </body>
    </html>
    

    This code worked well when I set the image path as source for <img> html tag. However, when I pass the source as base64String does not work.

    How to achieve what I want?

  • Andy E
    Andy E over 12 years
    Note that atob and btoa have never been part of any standard. They are supported by some standards-compliant browsers, but don't count on it being in all of them.
  • John Doe
    John Doe over 12 years
    @AndyE Correct. That's why you have to perform feature testing before using these methods.
  • vengatesh
    vengatesh over 12 years
    @John Doe : still i couldn't get the save dialogue box for saving the image to user's disk
  • John Doe
    John Doe over 12 years
    @vengatesh : please see the updated answer. keep in mind that you'll have to specify the correct file extension in order to have your image saved properly.
  • vengatesh
    vengatesh over 12 years
    @John Doe:thanks alot . but it doesn't work with IE ,can we get the file location from from user? can we have the same file format as before?. because all are saved as .part file.
  • John Doe
    John Doe over 12 years
    @vengatesh : that's right, you have to specify the full filename including an extension (e.g., png). could you please clarify your objective? what do you mean by "can we get the file location from from user? can we have the same file format as before?"?
  • vengatesh
    vengatesh over 12 years
    @Johm Doe:Actually my needs are 1) i want to open a save dialog for storing the image (in html page) 2)the image file was in PNG format before it was converted into base64String, but your code saves the image as eg.part format.here i want the image to be stored in PNG format itself.
  • John Doe
    John Doe over 12 years
    @vengatesh : This is not my code that proposes you to save file in a *.part format - this is how browser handles the request, since the image is not bytecoded. There is no easy way to achieve a goal. One of possible solutions is configuring a server to respond with certain headers that contain filename and extension - you should google on that matter...
  • benedict_w
    benedict_w over 11 years
    @JohnDoe - Thanks for this answer I used it to build a solution I had to a similar problem and it works perfectly! Only one thing I would like to provide a name for the file download the browser currently it defaults to 'download' (in Chrome anyway). Any ideas?
  • John Doe
    John Doe over 11 years
    @benedict_w Yeah, I had the same problem. In order to let a browser know how to name a file (including extension) I used a PHP-script that modified content-disposition header in an HTTP-response. Hope this helps!
  • benedict_w
    benedict_w over 11 years
    Yeah I also tried this with header('Content-Disposition: attachment; filename="my-image.png"'); but it didn't work (my image is already generated via a server side script). Did you use the technique here? greenethumb.com/article/1429/… - I don't really want to send my bytecode back to the server if I don't have to!
  • John Doe
    John Doe over 11 years
    @benedict_w I guess it was a similar logic, except for getting data from canvas (just adding the HTTP-headers).
  • John Doe
    John Doe over 8 years
    @Ankita, I suppose you can use the loaded image source attribute value.
  • Maninder
    Maninder over 8 years
    @JohnDoe can you tell me how to create data url for image, as I am showing image from database to table. So I have to add functionality to download image. Thanks
  • Eric Hodonsky
    Eric Hodonsky about 7 years
    @vengatesh you should accept this answer for the responder. Thanks guys!
  • Alex78191
    Alex78191 over 6 years
    Now Safari is supported.
  • heringer
    heringer over 5 years
    For me, it worked on Chrome, but it did not work on Firefox. Does anyone face the same problem?
  • Sabrina Luo
    Sabrina Luo about 5 years
    jsfiddle is dead :(
  • Pedro Vagner
    Pedro Vagner about 5 years
    On Firefox, the anchor tag must be added to DOM in order to click event work. See stackoverflow.com/q/48642223/1882644