0

I use an Image to load a picture onto a canvas.
I would then like to be able to my User the option to save the image to their hard drive.

I have searched around and there are plenty of ways to do this IF I use Ajax and retrieve from my server.

Is there a way to avoid any trips to my server and to save directly onto my hard drive either via the image control or the canvas control

Andrew Simpson
  • 6,883
  • 11
  • 79
  • 179
  • 2
    No, this a security risk and is blocked for good reason. – John Conde Mar 13 '15 at 13:45
  • @JohnConde Thank you. It is what i thought. Saves me looking :) – Andrew Simpson Mar 13 '15 at 13:45
  • @JohnConde Doesn't `canvas` have a `toDataURL()` method? Could it not be used to create a link, from which the image could be "downloaded"? – Sverri M. Olsen Mar 13 '15 at 13:47
  • @SverriM.Olsen That doesn't actually save the image to the user's HD but does facilitate it happening. – John Conde Mar 13 '15 at 13:48
  • i've seen this done with a js pdf generate, it is able to create the pdf and then save with out going to the server (here is an example i made for a different question http://stackoverflow.com/questions/25630811/export-highcharts-to-pdf-using-javascript-and-local-server-no-internet-connec/25632935#25632935) might be something in there that allows you to do this – Quince Mar 13 '15 at 13:48
  • @JohnConde I agree it could be considered a security risk, but still it can be done... and even without the user's interaction. I personally find some of the new HTML5 features, like the `download` attribute or the `File` API, interesting in that sense – Alvaro Montoro Mar 13 '15 at 15:23
  • Would you thinking being a security risk they will patch it up so it will not be available in the future? – Andrew Simpson Mar 13 '15 at 17:09
  • 1
    I don't think they'll patch it because it was not considered a security issue, and it made it to the standard recommendation: http://www.w3.org/TR/html5/links.html#attr-hyperlink-download – Alvaro Montoro Mar 13 '15 at 17:30
  • You may have a point. Thanks for that link – Andrew Simpson Mar 13 '15 at 17:31

2 Answers2

2

You can actually get the effect you want by using the HTML5 download attribute.

The steps would be:

  1. Create your image with the canvas
  2. Append an invisible link with the download attribute
  3. Trigger the link onclick event
  4. Remove the hidden link

Something like this:

myCanvas = document.getElementById("myCanvas");

$("body").append("<a id='hiddenLink' href='" + myCanvas.toDataURL() + "' style='display:none;' download>Download Pic</a>");
$("#hiddenLink")[0].click();
$("#hiddenLink").remove();

You can see it working here: http://jsfiddle.net/wLd4yf7k/

One issue: not all the browsers will support it: http://caniuse.com/#feat=download


And here you have a solution using exclusively JavaScript (no jQuery), as I see that you didn't add a jQuery tag to the question:

myCanvas = document.getElementById("myCanvas");

a = document.createElement("a");
a.href = myCanvas.toDataURL();
a.download = "download";
a.click();

You can see it working on the fiddle: http://jsfiddle.net/wLd4yf7k/1/

Alvaro Montoro
  • 28,081
  • 7
  • 57
  • 86
  • Two notes: 1) You could have a link already on the page (saving step 2 and 4, but would need to update the `href`); and 2) I used the canvas example from the w3schools site (not really relevant to the answer, but just in case somebody says I didn't credit the source or something) – Alvaro Montoro Mar 13 '15 at 14:24
  • oh i did not know about this, nice. in the cases where it is not supported you could just then fall back to open in a tab method but this works really nicely – Quince Mar 13 '15 at 14:32
  • Sorry for the delay.just got back to my desk. Is there anyway to control where is saves it to? It will default to my download directory (as expected) – Andrew Simpson Mar 13 '15 at 17:15
  • From the link above: "If the attribute has a value, the value will be used as the pre-filled file name in the Save prompt that opens when the user clicks on the link". I tested and it only works with names, and doesn't allow paths (that would be bad) – Alvaro Montoro Mar 13 '15 at 17:24
1

So you can almost do this. In my comment i mention a pdf generator that creates and downloads a pdf file. This works because when opening a pdf file the automatic action for the browser (in most cases) is to download the file. When you do this with an image it will open in a new tab but you can at least right click and save.

It works by calling window.open on the canvases toDataUrl()

here is an example using chartjs

var data = {
    labels: ["January", "February", "March", "April", "May", "June", "July"],
    datasets: [
        {
            label: "My First dataset",
            fillColor: "rgba(220,220,220,0.2)",
            strokeColor: "rgba(220,220,220,1)",
            pointColor: "rgba(220,220,220,1)",
            pointStrokeColor: "#fff",
            pointHighlightFill: "#fff",
            pointHighlightStroke: "rgba(220,220,220,1)",
            data: [65, 59, 80, 81, 56, 55, 40]
        },
        {
            label: "My Second dataset",
            fillColor: "rgba(151,187,205,0.2)",
            strokeColor: "rgba(151,187,205,1)",
            pointColor: "rgba(0,0,0,0)",
            pointStrokeColor:  "rgba(0,0,0,0)",
            pointHighlightFill: "rgba(0,0,0,0)",
            pointHighlightStroke: "rgba(151,187,205,1)",
            data: [28, 48, 40, 19, 86, 27, 90]
        }
    ]
};



    var chart_canvas = document.getElementById("canvas").getContext("2d");
    var line_chart= new Chart(chart_canvas).Line(data);

$("button").on("click", function(){
     window.open(document.getElementById("canvas").toDataURL()); 
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/1.0.1/Chart.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="chart_container"style="width: 50%">
    <canvas id="canvas" height="450" width="600"></canvas>
    <button> save </button>
</div>
Quince
  • 14,790
  • 6
  • 60
  • 69