25

I have an image encoded in base64 in a javascript variable : data:image/png;base64, base64 data

[EDIT] I need to save that file to disk without asking to the visitor to do a right click [/EDIT]

Is it possible ? How ?

Thanks in advance

Best regards

hotips
  • 2,575
  • 7
  • 42
  • 59
  • You can't. You can read this [post](https://stackoverflow.com/questions/461791/can-you-write-to-a-file-on-a-disk-in-javascript). – Spilarix Oct 11 '10 at 12:28

10 Answers10

47

I know this question is 2 years old, but hopefully people will see this update.

You can prompt the user to save an image in a base64 string (and also set the filename), without asking the user to do a right click

var download = document.createElement('a');
download.href = dataURI;
download.download = filename;
download.click();

Example:

var download = document.createElement('a');
download.href = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==';
download.download = 'reddot.png';
download.click();

In order to trigger a click event using Firefox, you need to do what it is explained in this SO answer. Basically:

function fireEvent(obj,evt){
  var fireOnThis = obj;
  if(document.createEvent ) {
    var evObj = document.createEvent('MouseEvents');
    evObj.initEvent( evt, true, false );
    fireOnThis.dispatchEvent( evObj );
  } else if( document.createEventObject ) {
    var evObj = document.createEventObject();
    fireOnThis.fireEvent( 'on' + evt, evObj );
  }
}
fireEvent(download, 'click')

As of 20/03/2013, the only browser that fully supports the download attribute is Chrome. Check the compatibility table here

Community
  • 1
  • 1
davoclavo
  • 1,432
  • 16
  • 19
6

I am surprised nobody here mentioned using HTML5 blobs together with a couple of nice libraries.

You first need https://github.com/eligrey/FileSaver.js/ and https://github.com/blueimp/JavaScript-Canvas-to-Blob.

Then you can load the image into a canvas

base_image = new Image();
base_image.src ='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==';

the canvas into a blob

var canvas = document.getElementById('YourCanvas');
context = canvas.getContext('2d');
// Draw image within
context.drawImage(base_image, 0,0);

and finally save it

x_canvas.toBlob(function(blob) {
saveAs(blob, "screenshot.png");
}, "image/png");

FF is not fully supported but at least you get a separate page with the image.

Check this out: http://jsfiddle.net/khhmm/9/

EDIT: this is not compatible with Safari / Mac.

malber
  • 1,053
  • 4
  • 16
  • 24
  • Suppose JS is used to draw encoded data to the canvas and that the image is not cached in any way in browser-----Is it still possible to dump the canvas (perhaps "duplicate" would be a better term) and then programmatically save it in my browser's cache (or elsewhere)? Do you have a blog or some other contact point? (possible consulting offer?) – telefunkenvf14 Mar 31 '13 at 03:05
  • Sorry I am not sure how you can achieve this. – malber Apr 02 '13 at 14:46
  • 1
    Thanks! This saved me a lot of heartache. I had gotten to Blob and FileSaver.js but couldn't figure out how to put them together. Great stuff. – Vinny Sep 18 '14 at 18:05
6

... without asking to the visitor anyhing ... Is it possible?

No, that would have been a security hole. If it was possible, one would be able to write malware to the enduser's disk unaskingly. Your best bet may be a (signed) Java Applet. True, it costs a bit of $$$ to get it signed (so that it doesn't pop security warnings), but it is able to write data to enduser's disk without its permission.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
3

As other answers already stated, you cannot do it only with javascript. If you want, you can send the data (using normal HTTP POST) to a PHP script, call header('Content-type: image/png') and output the decoded image data to the page using echo base64_decode($base64data).

This will work just as if user clicked on an image and open it or prompt him to save the file to disk (the normal browser's save file dialog).

user323094
  • 3,643
  • 4
  • 21
  • 30
2

It's not possible.

If it was, browsers would be massively insecure, being able to write random data to your hard disk without user interaction.

Jerod Venema
  • 44,124
  • 5
  • 66
  • 109
1

with javascript, you can't. the only real possibility i can think of will be a java-applet, but maybe (i don't know how long that image should be saved) you could simply add an img-tag with you png and force caching (but if the user deletes his cache, the image will be gone).

oezi
  • 51,017
  • 10
  • 98
  • 115
0

I think it's possible with JavaScript if you use ActiveX.

Another possibility is to make the server spit out that file with a different mime type so the browser asks the user to save it.

Julio Santos
  • 3,837
  • 2
  • 26
  • 47
  • 1
    Using ActiveX restricts you however to a single webbrowser type (MSIE) and even then, MSIE in its default setup will scare the enduser with all kinds of security warnings before continuing. ActiveX, no thanks. – BalusC Oct 11 '10 at 12:35
0

You can make this file as blob on the server and use setTimeout function in order to fire the download.

Footer
  • 129
  • 4
0

I think you can do it something(maybe not only with javascript...xul programming needed). There are Firefox addons that save images to a folder(check Firefox addons site)

ionutcib
  • 257
  • 1
  • 2
  • 10
0

The accepted solution seems to have a limitation for large data. If you're running into this (instead of the downloaded file's name, I see "download" and "Failed - Network error" in Chrome), here's what I did in order to download a 2mb file:

const blob = await (await fetch(document.getElementById('canvasID').toDataURL())).blob();
const file = new File([blob], {type:"image/png", lastModified: new Date()});
var a = document.createElement('a');
a.href = window.URL.createObjectURL(file);
a.download = 'image.png';
a.click();
Nate
  • 1,268
  • 13
  • 20