浏览器/ HTML强制从src =“ data:image / jpeg; base64…”下载图像


85

我在客户端生成图像,并使用HTML显示如下:

<img src="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAMCAgICAgM...."/>

我想提供下载生成的图像的可能性。

我怎么能知道浏览器正在打开文件保存对话框(或者只是将chrome或firefox这样的图像下载到下载文件夹即可),从而允许用户保存图像而无需右键单击并另存为图像?

我希望没有服务器交互的解决方案。因此,我知道如果我先上传图像然后开始下载,那将是可能的。

非常感谢!

Answers:


119

只需替换image/jpegapplication/octet-stream。客户端不会将URL识别为可内联资源,并提示下载对话框。

一个简单的JavaScript解决方案是:

//var img = reference to image
var url = img.src.replace(/^data:image\/[^;]+/, 'data:application/octet-stream');
window.open(url);
// Or perhaps: location.href = url;
// Or even setting the location of an <iframe> element, 

另一种方法是使用blob:URI:

var img = document.images[0];
img.onclick = function() {
    // atob to base64_decode the data-URI
    var image_data = atob(img.src.split(',')[1]);
    // Use typed arrays to convert the binary data to a Blob
    var arraybuffer = new ArrayBuffer(image_data.length);
    var view = new Uint8Array(arraybuffer);
    for (var i=0; i<image_data.length; i++) {
        view[i] = image_data.charCodeAt(i) & 0xff;
    }
    try {
        // This is the recommended method:
        var blob = new Blob([arraybuffer], {type: 'application/octet-stream'});
    } catch (e) {
        // The BlobBuilder API has been deprecated in favour of Blob, but older
        // browsers don't know about the Blob constructor
        // IE10 also supports BlobBuilder, but since the `Blob` constructor
        //  also works, there's no need to add `MSBlobBuilder`.
        var bb = new (window.WebKitBlobBuilder || window.MozBlobBuilder);
        bb.append(arraybuffer);
        var blob = bb.getBlob('application/octet-stream'); // <-- Here's the Blob
    }

    // Use the URL object to create a temporary URL
    var url = (window.webkitURL || window.URL).createObjectURL(blob);
    location.href = url; // <-- Download!
};

Relevant documentation


1
for some reason it seams to be broken in Chrome 19.0 beta but it works on Chrome 18 and Firefox so I am fine. Is there a possibility to set a file name?
alex

There is no way to set the file name in a data-URI. Even when a canvas / Blob is used to export the data, the file name cannot be set. I've added another method to my answer (I guess that this one will work in Chrome 19).
Rob W

2
Do you think the first method is going to be deprecated because it is not working in chrome 19 anymore?
alex

1
I can't find a relevant source on it. I've also found this answer, by the way, which suggests how to set a default name in Chrome (anchors only, the user has to click on it)
Rob W

Also found this solutions - seems to be chrome only for now. Thanks for your support!
alex

96

you can use the download attribute on an a tag ...

<a href="data:image/jpeg;base64,/9j/4AAQSkZ..." download="filename.jpg"></a>

see more: https://developer.mozilla.org/en/HTML/element/a#attr-download


1
How can I use this solution when I generate the image source dynamically? I mean I have Download button, when user clicks on it, I do some calculations, generate base64 image and ... how can I force downloading?
Mikhail

In chrome I cannot set the filename using this method. The downloaded file's name remains "download" no matter what. This only happens when using data:image...
cmaduro

5
I know this is an old post but according to W3Schools website 'download' attribute is not supported by IE, Safari and Opera v. < 12 w3schools.com/tags/tryit.asp?filename=tryhtml5_a_download2 in fact I tried it with IE and it does not work.... :(
Mirko Lugano

6
At the time of this comment, the download attribute still isn't supported Safari and IE.
TheCarver

1
it have base64 length limitation you can't download larger images using this approch.
Kiran Chenna

15

I guess an img tag is needed as a child of an a tag, the following way:

<a download="YourFileName.jpeg" href="data:image/jpeg;base64,iVBO...CYII=">
    <img src="data:image/jpeg;base64,iVBO...CYII="></img>
</a>

or

<a download="YourFileName.jpeg" href="/path/to/OtherFile.jpg">
    <img src="/path/to/OtherFile.jpg"></img>
</a>

Only using the a tag as explained in #15 didn't worked for me with the latest version of Firefox and Chrome, but putting the same image data in both a.href and img.src tags worked for me.

From JavaScript it could be generated like this:

var data = canvas.toDataURL("image/jpeg");

var img = document.createElement('img');
img.src = data;

var a = document.createElement('a');
a.setAttribute("download", "YourFileName.jpeg");
a.setAttribute("href", data);
a.appendChild(img);

var w = open();
w.document.title = 'Export Image';
w.document.body.innerHTML = 'Left-click on the image to save it.';
w.document.body.appendChild(a);

it's not that it needs an img tag inside, the MSDN docs state that only already downloaded resources can be used - should work as long as you have the image with the same data:base64 anywhere. msdn.microsoft.com/en-us/library/cc848897.aspx -- "For security reasons, data URIs are restricted to downloaded resources. Data URIs cannot be used for navigation, for scripting, or to populate frame or iframe elements."
Dimitar Christoff

5

Take a look at FileSaver.js. It provides a handy saveAs function which takes care of most browser specific quirks.

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.