84 votos

Navegador/HTML Forzar la descarga de la imagen desde src="data:image/jpeg;base64..."

Estoy generando una imagen en el lado del cliente y la muestro con el HTML así:

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

Quiero ofrecer la posibilidad de descargar la imagen generada.

¿Cómo puedo darme cuenta de que el navegador está abriendo un diálogo para guardar el archivo (o simplemente descargar la imagen como lo haría Chrome o Firefox a la carpeta de descargas) que permite al usuario guardar la imagen sin hacer clic derecho y guardar como en la imagen?

Preferiría una solución sin interacción con el servidor. Así que soy consciente de que sería posible si primero subo la imagen y luego comienzo la descarga.

¡Muchas gracias!

117voto

Rob W Puntos 125904

Simplemente sustituye image/jpeg con application/octet-stream . El cliente no reconocería la URL como un recurso en línea, y provocaría un diálogo de descarga.

Una simple solución de JavaScript sería : http://jsfiddle.net/5whKM/

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

Otro método es utilizar un blob: URI : http://jsfiddle.net/5whKM/13/

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

Documentación pertinente

No lo he intentado todavía, pero un filesystem: -URL también podría funcionar (Sólo cromo, por el momento). Ver HTML5 Rocas para más información.

96voto

Bruce Aldridge Puntos 1498

puedes usar el atributo de descarga en una etiqueta ...

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

ver más: https://developer.mozilla.org/en/HTML/element/a#attr-download

14voto

user3521208 Puntos 21

Supongo que un img se necesita como hijo de un a la etiqueta, de la siguiente manera:

<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="http://stackoverflow.com/path/to/OtherFile.jpg">
    <img src="/path/to/OtherFile.jpg"></img>
</a>

Sólo usando el a como se explica en #15 no me funcionó con la última versión de Firefox y Chrome, pero poner los mismos datos de imagen en ambos a.href y img.src las etiquetas funcionaron para mí.

Desde JavaScript se podría generar así:

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

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X