如何从JavaScript变量中保存PNG

25
我有一个以base64编码的图像存储在Javascript变量中:data:image/png;base64, base64数据

[编辑] 我需要将该文件保存到磁盘而无需要求访问者右键单击。

是否有可能?如何实现?

谢谢!

最好的祝福


你不能这样做。你可以阅读这篇文章:(https://dev59.com/43RB5IYBdhLWcg3w77kn)。 - Spilarix
10个回答

47

我知道这个问题已经两年了,但希望人们能看到这个更新。

您可以提示用户在不要求用户执行右键单击的情况下保存以base64字符串形式表示的图像(并设置文件名)。

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

例子:

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

要使用Firefox触发点击事件,您需要按照这个SO回答中所解释的方式操作。基本上:

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')
截至2023年3月20日,唯一完全支持download属性的浏览器是Chrome。在这里查看兼容性表格

1
在Chrome中完美运行,但在使用Google Chrome Frame的IE8中没有任何作用。 - Mike Gledhill
1
如果您正在使用jQuery,请使用$(download).click()。如果您没有使用jQuery,请查看这个其他的SO问题 - davoclavo
1
我认为这在FF,IE上不起作用。它甚至没有对事件做出反应,这可能会让用户想知道发生了什么。 - malber
1
我该如何将它保存在目录中? - Benjamin G
非常棒的答案。使用起来非常简单。 - Orion
对我来说非常有效 :) - Alireza

6
我很惊讶这里没有人提到使用HTML5 blob和一些好的库。
首先你需要使用两个库:https://github.com/eligrey/FileSaver.js/https://github.com/blueimp/JavaScript-Canvas-to-Blob
然后你可以将图片加载到画布中。
base_image = new Image();
base_image.src ='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==';

将画布转换为 Blob
var canvas = document.getElementById('YourCanvas');
context = canvas.getContext('2d');
// Draw image within
context.drawImage(base_image, 0,0);

最后将其保存。
x_canvas.toBlob(function(blob) {
saveAs(blob, "screenshot.png");
}, "image/png");

FF(Firefox浏览器)不完全支持,但至少您能得到一个包含图像的单独页面。

看看这个:http://jsfiddle.net/khhmm/9/

编辑:这不兼容Safari / Mac。


假设使用JS将编码数据绘制到画布上,并且图像在浏览器中没有被缓存——是否仍然可以转储画布(也许“复制”是更好的术语),然后以编程方式将其保存在我的浏览器缓存(或其他地方)中?您是否有博客或其他联系方式?(可能有咨询需求?) - telefunkenvf14
抱歉,我不确定你如何实现这个。 - malber
1
谢谢!这节省了我很多烦恼。我已经到了Blob和FileSaver.js,但是无法弄清楚如何将它们组合在一起。太棒了。 - Vinny

6

...不向访问者询问任何内容...这可能吗?

不,那将是一个安全漏洞。如果可能的话,恶意软件可以在未经许可的情况下写入终端用户的磁盘。您最好选择(签名的)Java Applet。确实,它需要一些$$$来签名(以避免弹出安全警告),但它能够在未经许可的情况下向终端用户的磁盘写入数据。


3

正如其他回答所述,你无法仅使用javascript实现。如果你想要,可以将数据(使用普通的HTTP POST)发送到一个PHP脚本,调用header('Content-type: image/png')并使用echo base64_decode($base64data)将解码后的图像数据输出到页面上。

这将与用户点击图像并打开它或提示他将文件保存到磁盘(正常浏览器的保存文件对话框)一样有效。


2

这是不可能的。

如果可以实现,浏览器将会极度不安全,能够在没有用户交互的情况下向您的硬盘写入随机数据。


1

使用JavaScript是不可能的。我能想到的唯一真正的可能性是使用Java小程序,但也许(我不知道这个图像应该保存多长时间)你可以简单地添加一个img标签和强制缓存(但如果用户删除了缓存,图像将会消失)。


0

已接受的解决方案似乎对大数据有限制。如果您遇到这个问题(在Chrome中,我看到“下载”和“失败-网络错误”而不是下载文件名),以下是我下载2MB文件所做的操作:

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();

0

我认为你可以做到这件事情(可能不仅限于JavaScript...需要XUL编程)。有一些Firefox插件可以将图片保存到文件夹中(请查看Firefox插件网站)。


很抱歉,但“我认为你可以,去检查一下插件”不是一个答案。 - Igor Zinov'yev

0

如果使用ActiveX,我认为可以通过JavaScript实现。

另一种可能性是让服务器以不同的MIME类型输出该文件,这样浏览器会要求用户保存它。


1
使用ActiveX会限制您只能使用单个Web浏览器类型(MSIE),即使是在默认设置下,MSIE也会在继续之前向最终用户发出各种安全警告。ActiveX,不用了。 - BalusC

0
您可以将此文件作为服务器上的 blob,并使用 setTimeout 函数以触发下载。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接