Browser / HTML Forza il download dell'immagine da src = "data: image / jpeg; base64…"


85

Sto generando un'immagine sul lato client e la visualizzo con HTML in questo modo:

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

Voglio offrire la possibilità di scaricare l'immagine generata.

Come posso rendermi conto che il browser sta aprendo un file save dialoge (o semplicemente scaricare l'immagine come chrome o firefox nella cartella di download farebbe) che consente all'utente di salvare l'immagine senza fare clic con il tasto destro e salvare come sull'immagine?

Preferirei una soluzione senza interazione con il server. Quindi sono consapevole che sarebbe possibile caricare prima l'immagine e poi avviare il download.

Molte grazie!

Risposte:


119

Sostituisci semplicemente image/jpegcon application/octet-stream. Il client non riconoscerebbe l'URL come risorsa in linea e richiederebbe una finestra di dialogo per il download.

Una semplice soluzione JavaScript sarebbe:

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

Un altro metodo consiste nell'usare un 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!
};

Documentazione pertinente


1
per qualche ragione sembra essere rotto in Chrome 19.0 beta ma funziona su Chrome 18 e Firefox, quindi sto bene. C'è la possibilità di impostare un nome file?
alex

Non è possibile impostare il nome del file in un URI di dati. Anche quando si utilizza una tela / Blob per esportare i dati, il nome del file non può essere impostato. Ho aggiunto un altro metodo alla mia risposta (immagino che questo funzionerà in Chrome 19).
Rob W

2
Pensi che il primo metodo sarà deprecato perché non funziona più in Chrome 19?
alex

1
Non riesco a trovare una fonte pertinente su di esso. Ho anche trovato questa risposta , a proposito, che suggerisce come impostare un nome predefinito in Chrome (solo ancore, l'utente deve fare clic su di esso)
Rob W

Ho anche trovato questa soluzione - sembra essere cromato solo per ora. Grazie per il vostro sostegno!
alex

96

puoi usare l'attributo download su un tag ...

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

vedi di più: https://developer.mozilla.org/en/HTML/element/a#attr-download


1
Come posso utilizzare questa soluzione quando generi dinamicamente la sorgente dell'immagine? Voglio dire, ho il pulsante Download, quando l'utente fa clic su di esso, eseguo alcuni calcoli, genera un'immagine base64 e ... come posso forzare il download?
Mikhail

In Chrome non posso impostare il nome del file usando questo metodo. Il nome del file scaricato rimane "download" qualunque cosa accada. Questo accade solo quando si utilizzano i dati: immagine ...
cmaduro

5
So che questo è un vecchio post ma secondo l'attributo 'download' del sito web di W3Schools non è supportato da IE, Safari e Opera v. <12 w3schools.com/tags/tryit.asp?filename=tryhtml5_a_download2 infatti l'ho provato con IE e non funziona .... :(
Mirko Lugano

6
Al momento di questo commento, l' downloadattributo non è ancora supportato Safari e IE.
TheCarver

1
ha un limite di lunghezza base64, non è possibile scaricare immagini più grandi utilizzando questo approccio.
Kiran Chenna

15

Credo che un img tag è necessaria come figlio di un un tag, nel seguente modo:

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

o

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

Solo utilizzando l' una tag come spiegato nella # 15 non ha funzionato per me con l'ultima versione di Firefox e Chrome, ma mettere gli stessi dati di immagine sia in a.href e img.src tag funzionato per me.

Da JavaScript potrebbe essere generato in questo modo:

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

non è che abbia bisogno di un tag img all'interno, i documenti di MSDN affermano che possono essere utilizzate solo le risorse già scaricate - dovrebbe funzionare fintanto che hai l'immagine con gli stessi dati: base64 ovunque. msdn.microsoft.com/en-us/library/cc848897.aspx - "Per motivi di sicurezza, gli URI dei dati sono limitati alle risorse scaricate. Gli URI dei dati non possono essere utilizzati per la navigazione, per lo scripting o per popolare elementi frame o iframe."
Dimitar Christoff

5

Dai un'occhiata a FileSaver.js . Fornisce una comoda saveAsfunzione che si prende cura della maggior parte delle stranezze specifiche del browser.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.