Sand boxing
Browsers are sand-boxed when it deals with saving content to user's hard disk. This is for security (you don't want a bad hacker (or spy) to overwrite system files or plant a virus or a backdoor etc.). So direct access is prevented and local storage is isolated.
You always need to "bridge" the content by an user interaction that approves the operation and therefor the browser will request you to choose a location for the file by popping up a dialog to make the user aware of that the browser tries to deliver content to be saved (see demo below).
Invoking save dialogs
Here are a couple of other possibilities to enable download.
If a link for example under the image is ok then you can do:
/// create an anchor/link (or use an existing)
var lnk = document.createElement('a');
/// set your image as data-uri link
lnk.href = canvas.toDataURL();
/// and the key, when user click image will be downloaded
lnk.download = 'filename.png';
/// add lnk to DOM, here after the canvas
canvas.parentElement.appendChild(lnk);
The download attribute is a new HTML5 feature. Instead of "navigating" to this location the browser will show a save dialog instead and let the user save its content to disk.
You can also automate the whole clicking feature by generating an event for it.
For example:
function download(canvas, filename) {
if (typeof filename !== 'string' || filename.trim().length === 0)
filename = 'Untitled';
var lnk = document.createElement('a'),
e;
lnk.download = filename;
lnk.href = canvas.toDataURL();
if (document.createEvent) {
e = document.createEvent("MouseEvents");
e.initMouseEvent('click', true, true, window,
0, 0, 0, 0, 0, false, false,
false, false, 0, null);
/// send event
lnk.dispatchEvent(e);
} else if (lnk.fireEvent) {
lnk.fireEvent("onclick");
}
}
Saving to server
You can always go by the step of saving the file to a server. However, you will also have to go through the save dialog step when retrieving the file from server (the dialog).
If you want to store the file only to be shown in the browser this is perfect.
There are various ways to do this (there are many solutions on SO for this).
Local storage
And a different option is to store the file in the browser's local storage. You have Web Storage, however this is very limited (typically between 2.5 - 5 mb) and considering that each char stored takes two bytes the actual storage is just half of that (it can only store strings such as the data-uri and data-uris is about 33% larger than the original file). But if you save small icons, sprites etc. this might do.
In addition you can use Indexed DB (and the now deprectaed Web SQL) which can store larger data and you can also request user's permission to store x mb of dat.
The same goes with File API (which is currently only implemented in Chrome). This acts more like a file system and is intended to store huge files.
These might seem more complex if you are not familiar with them, but I mention them as possible options as these also saves you bandwidth communicating with a server and you move the "burden" to the client instead of the server.