web-dev-qa-db-fra.com

Navigateur / HTML Forcer le téléchargement de l'image à partir de src = "data: image / jpeg; base64 ..."

Je génère une image côté client et je l'affiche avec HTML comme ceci:

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

Je souhaite offrir la possibilité de télécharger l'image générée.

Comment puis-je me rendre compte que le navigateur ouvre une boîte de dialogue de sauvegarde de fichier (ou télécharge simplement l'image comme chrome ou firefox dans le dossier de téléchargement), ce qui permet à l'utilisateur de sauvegarder l'image sans le faire clic droit et enregistrer sous sur l'image?

Je préférerais une solution sans interaction serveur. Donc, je suis conscient que ce serait possible si je téléchargeais d'abord l'image puis commençais le téléchargement.

Merci beaucoup!

81
alex

Remplacez simplement _image/jpeg_ par _application/octet-stream_. Le client ne reconnaît pas l'URL en tant que ressource pouvant être intégrée et invite une boîte de dialogue de téléchargement.

Une solution JavaScript simple serait:

_//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, 
_

Une autre méthode consiste à utiliser un URI _blob:_:

_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!
};
_

Documentation pertinente

112
Rob W

vous pouvez utiliser l'attribut de téléchargement sur une balise ...

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

voir plus: https://developer.mozilla.org/en/HTML/element/a#attr-download

86
Bruce Aldridge

Je suppose qu'une balise img est nécessaire en tant qu'enfant d'une balise a, de la manière suivante:

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

ou

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

Utiliser seulement la balise a comme expliqué dans # 15 ne fonctionnait pas pour moi avec les versions les plus récentes de Firefox et Chrome, mais mettre les mêmes données d'image dans les deux a.href et img.src les tags ont fonctionné pour moi.

A partir de JavaScript, il pourrait être généré comme ceci:

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);
14
user3521208

Jetez un oeil à FileSaver.js . Il fournit une fonction pratique saveAs qui prend en charge la plupart des bizarreries propres au navigateur.

5
jesal