Download image with JavaScript

202,048

Solution 1

The problem is that jQuery doesn't trigger the native click event for <a> elements so that navigation doesn't happen (the normal behavior of an <a>), so you need to do that manually. For almost all other scenarios, the native DOM event is triggered (at least attempted to - it's in a try/catch).

To trigger it manually, try:

var a = $("<a>")
    .attr("href", "http://i.stack.imgur.com/L8rHf.png")
    .attr("download", "img.png")
    .appendTo("body");

a[0].click();

a.remove();

DEMO: http://jsfiddle.net/HTggQ/

Relevant line in current jQuery source: https://github.com/jquery/jquery/blob/1.11.1/src/event.js#L332

if ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) &&
        jQuery.acceptData( elem ) ) {

Solution 2

As @Ian explained, the problem is that jQuery's click() is not the same as the native one.

Therefore, consider using vanilla-js instead of jQuery:

var a = document.createElement('a');
a.href = "img.png";
a.download = "output.png";
document.body.appendChild(a);
a.click();
document.body.removeChild(a);

Demo

Share:
202,048
Derek 朕會功夫
Author by

Derek 朕會功夫

Uh oh, sounds like somebody’s got a case of the Mondays! Are you using enough jQuery? http://i.stack.imgur.com/ssRUr.gif "Everybody stand back, I know regular expressions!" ─ xkcd 208

Updated on October 13, 2020

Comments

  • Derek 朕會功夫
    Derek 朕會功夫 over 3 years

    Right now I have a canvas and I want to save it as PNG. I can do it with all those fancy complicated file system API, but I don't really like them.

    I know if there is a link with download attribute on it:

    <a href="img.png" download="output.png">Download</a>
    

    it will download the file if the user clicks on it. Therefore I came up with this:

    $("<a>")
        .attr("href", "img.png")
        .attr("download", "output.png")
        .appendTo("body")
        .click()
        .remove();
    

    Demo: http://jsfiddle.net/DerekL/Wx7wn/

    However, it doesn't seem to work. Does it have to be trigger by an user action? Or else why didn't it work?

  • bafromca
    bafromca almost 10 years
    Could this be put inside a .each()? I can only seem to download one image at a time using this technique, probably has something to do with overloading the variable...
  • drzaus
    drzaus almost 10 years
    I don't think you need to attach/remove it from the DOM -- you should just be able to call $('<a>').attr(...)[0].click()
  • drzaus
    drzaus almost 10 years
  • Ian
    Ian almost 10 years
    @drzaus The attach/remove from the DOM was from the OP's code, it wasn't something I added. I kept the same code, but added the needed change (a[0].click()) which is the whole point. Just as well, the OP was using jQuery, so I kept with what they were using. But good points
  • Ian
    Ian almost 9 years
    @user963936 It looks like since Firefox 20, they only allow same-origin URLs for the download attribute (developer.mozilla.org/en-US/docs/Web/HTML/Element/…). If you inspect the DOM after the script runs, it looks like Firefox converts the tag to an <img>, and then jQuery loses its reference to it (why the .remove()) doesn't seem to do anything. Changing the href to point to a resource on the jsfiddle site seems to work in Firefox.
  • Ian
    Ian almost 9 years
    @user963936 Sorry I couldn't give a solution, only an explanation. I wasn't aware of browser quirks around this, I was just trying to solve the OP's original problem, which was that the .click() didn't work. I'm sure there's something that can be done in a different way to accomplish the same feature
  • Travis Tubbs
    Travis Tubbs over 7 years
    I am trying to do this same thing, but when I click the link it downloads the web page that I am on. I inspected the element and the link to the photo is in the download tag of the link. I am just modifying the attribute after the page loads though, does that matter?
  • Jsilvermist
    Jsilvermist almost 7 years
    Why append to body at all? It seems to work fine without doing so. Example: jsfiddle.net/azw08zt5/135
  • Oriol
    Oriol about 6 years
    @Jsilvermist Doesn't seem to work on Firefox if I don't insert the link into the tree.
  • Kapil Soni
    Kapil Soni over 3 years
    its working but also open image ,,in my case i have download only
  • Zeyad Shaban
    Zeyad Shaban almost 3 years
    It's not downloading it, it's just opening in a new window
  • Zeyad Shaban
    Zeyad Shaban almost 3 years
    It's working for some images like google images or so, but it doesn't work for images from professional websites like Pixabay or pixels as they require authenticated user so they return 403, however right clicking then save image as doesn't return 403, is there any way to make javascript just do a simple right click with save image as?
  • chovy
    chovy over 2 years
    Didn't do anything in firefox/linux
  • Grogu
    Grogu about 2 years
    This answer is no longer valid as 2022 because browsers have changed and now browsers will ALWAYS follow a link and open up a file it can read. The browsers only trigger a download if it cannot read the resource ie : zip or archive. stackoverflow.com/questions/51861852/…