Forzar al navegador a descargar archivos de imagen al hacer clic

100

Necesito que el navegador descargue los archivos de imagen tal como lo hace al hacer clic en una hoja de Excel.

¿Hay alguna forma de hacer esto usando solo la programación del lado del cliente?

<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title></title>
        <script type="text/javascript" src="Scripts/jquery-1.10.2.js">
        $(document).ready(function () {
            $("*").click(function () {
                $("p").hide();
            });
        });
        </script>
    </head>

    <script type="text/javascript">
        document.onclick = function (e) {
            e = e || window.event;
            var element = e.target || e.srcElement;
            if (element.innerHTML == "Image") {
                //someFunction(element.href);
                var name = element.nameProp;
                var address = element.href;
                saveImageAs1(element.nameProp, element.href);
                return false; // Prevent default action and stop event propagation
            }
            else
                return true;
        };

        function saveImageAs1(name, adress) {
            if (confirm('you wanna save this image?')) {
                window.win = open(adress);
                //response.redirect("~/testpage.html");
                setTimeout('win.document.execCommand("SaveAs")', 100);
                setTimeout('win.close()', 500);
            }
        }
    </script>

    <body>
        <form id="form1" runat="server">
            <div>
                <p>
                    <a href="http://localhost:55298/SaveImage/demo/Sample2.xlsx" target="_blank">Excel</a><br />
                    <a href="http://localhost:55298/SaveImage/demo/abc.jpg" id="abc">Image</a>
                </p>
            </div>
        </form>
    </body>
</html>

¿Cómo debería funcionar en caso de descargar una hoja de Excel (qué hacen los navegadores)?

Amit
fuente
7
El downloadatributo.
Šime Vidas
6
La mejor manera de garantizar la descarga de un archivo es establecer la disposición del contenido en el servidor, la mayoría de las soluciones del lado del cliente no son tan confiables.
adeneo
1
Posible duplicado: stackoverflow.com/questions/2408146/… ?
Karl-André Gagnon
Hay una pregunta similar que ya está respondida para usted: stackoverflow.com/a/6799284/1948211
dschu
Karl-Andre Gagnon: Por favor revíselo correctamente [no había etiquetado HTML 5 porque no quiero usarlo] y sin tocar el servidor
Amit

Respuestas:

172

Usando HTML5 puede agregar el atributo 'descargar' a sus enlaces.

<a href="https://stackoverflow.com/path/to/image.png" download>

Los navegadores compatibles le solicitarán que descargue la imagen con el mismo nombre de archivo (en este ejemplo image.png).

Si especifica un valor para este atributo, se convertirá en el nuevo nombre de archivo:

<a href="https://stackoverflow.com/path/to/image.png" download="AwesomeImage.png">

UPDATE: A partir de la primavera 2018 esto ya no es posible para la cruz-origen hrefs . Entonces, si desea crear <a href="https://i.imgur.com/IskAzqA.jpg" download>en un dominio que no sea imgur.com, no funcionará como se esperaba. Anuncio de eliminación y desactivación de Chrome

Richard Parnaby-King
fuente
Richard Parnaby-King: Usando el atributo HTML 5 se puede hacer, pero necesito hacerlo SIN usar HTML5 o cualquier herramienta del LADO DEL SERVIDOR (si es posible hacerlo) Gracias por los ayudantes :)
Amit
2
Aún no es totalmente compatible con todos los navegadores, pero es una buena solución si no te importa IE o Safari. caniuse.com/#feat=download
stacigh
Gracias por una solución HTML5. ¿Cómo seguir permitiendo 'guardar como' que me permita ingresar un nombre de archivo antes de guardar?
teleman
¿No puedo controlar dónde se debe descargar este archivo? Solo se descarga para descargar la carpeta directamente. Quiero que use la ruta local del archivo html.
Arjun Chiddarwar
1
@ArjunChiddarwar No, eso abre vulnerabilidades de seguridad (imagina que alguien guarda un archivo malicioso directamente en tu carpeta de Windows). La ruta de descarga se basa en la configuración del navegador; por ejemplo, Chrome se descargará de forma predeterminada en la carpeta de descargas.
Richard Parnaby-King
96

Logré que esto funcionara en Chrome y Firefox también agregando un enlace al documento.

var link = document.createElement('a');
link.href = 'images.jpg';
link.download = 'Download.jpg';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
SomnolenciaSaturno
fuente
2
Esta es en realidad una solución muy buena para aplicaciones web donde Javascript está por todas partes. Sin embargo, solo funciona en Google Chrome (en mi configuración de prueba).
Pavel
¿Alguna idea sobre una forma de probar la compatibilidad? Me gustaría usar esta técnica, pero también necesito ser compatible con otros navegadores, por lo que tendría que ofrecer una alternativa (como abrir un PDF en una nueva ventana o un enlace para descargar) cuando esto no sea compatible. ¿Alguien ha tenido suerte con eso?
alexrussell
13
¡Gran solución, gracias! Tenga en cuenta que si omite document.body.appendChild(link), no funcionará en Firefox. También es bueno eliminar el elemento creado con document.body.removeChild(link);afterlink.click()
akn
8
mejor solución. Para evitar la basura en el uso de DOMsetTimeout( function () { link.parentNode.removeChild( link ); },10 );
Mephiztopheles
1
Gracias debería haber sido la respuesta seleccionada, ya que la pregunta preguntaba cómo hacerlo en JAVASCRIPT.
codehelp4
33

Leeroy y Richard Parnaby-King:

ACTUALIZACIÓN: A partir de la primavera de 2018, esto ya no es posible para hrefs de origen cruzado. Entonces, si desea crear en un dominio que no sea imgur.com, no funcionará como se esperaba. Anuncio de eliminación y desactivación de Chrome

function forceDownload(url, fileName){
    var xhr = new XMLHttpRequest();
    xhr.open("GET", url, true);
    xhr.responseType = "blob";
    xhr.onload = function(){
        var urlCreator = window.URL || window.webkitURL;
        var imageUrl = urlCreator.createObjectURL(this.response);
        var tag = document.createElement('a');
        tag.href = imageUrl;
        tag.download = fileName;
        document.body.appendChild(tag);
        tag.click();
        document.body.removeChild(tag);
    }
    xhr.send();
}
IX
fuente
2
las descargas de imágenes, pero no se abre como se dice 'La imagen está roto'
picacode
18

Actualización primavera 2018

<a href="/path/to/image.jpg" download="FileName.jpg">

Si bien esto todavía es compatible, a partir de febrero de 2018 Chrome deshabilitó esta función para la descarga de origen cruzado, lo que significa que solo funcionará si el archivo se encuentra en el mismo nombre de dominio.

Descubrí una solución alternativa para descargar imágenes entre dominios después de la nueva actualización de Chrome que deshabilitó la descarga entre dominios. Puede modificar esto en una función que se adapte a sus necesidades. Es posible que pueda obtener la imagen de tipo mime (jpeg, png, gif, etc.) con un poco más de investigación si es necesario. También puede haber una forma de hacer algo similar a esto con videos. ¡Espero que esto ayude a alguien!

Leeroy y Richard Parnaby-King:

ACTUALIZACIÓN: A partir de la primavera de 2018, esto ya no es posible para hrefs de origen cruzado. Entonces, si desea crear en un dominio que no sea imgur.com, no funcionará como se esperaba. Anuncio de eliminación y desactivación de Chrome

var image = new Image();
image.crossOrigin = "anonymous";
image.src = "https://is3-ssl.mzstatic.com/image/thumb/Music62/v4/4b/f6/a2/4bf6a267-5a59-be4f-6947-d803849c6a7d/source/200x200bb.jpg";
// get file name - you might need to modify this if your image url doesn't contain a file extension otherwise you can set the file name manually
var fileName = image.src.split(/(\\|\/)/g).pop();
image.onload = function () {
    var canvas = document.createElement('canvas');
    canvas.width = this.naturalWidth; // or 'width' if you want a special/scaled size
    canvas.height = this.naturalHeight; // or 'height' if you want a special/scaled size
    canvas.getContext('2d').drawImage(this, 0, 0);
    var blob;
    // ... get as Data URI
    if (image.src.indexOf(".jpg") > -1) {
    blob = canvas.toDataURL("image/jpeg");
    } else if (image.src.indexOf(".png") > -1) {
    blob = canvas.toDataURL("image/png");
    } else if (image.src.indexOf(".gif") > -1) {
    blob = canvas.toDataURL("image/gif");
    } else {
    blob = canvas.toDataURL("image/png");
    }
    $("body").html("<b>Click image to download.</b><br><a download='" + fileName + "' href='" + blob + "'><img src='" + blob + "'/></a>");
};
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Riley Bell
fuente
Parece que este código decodifica la imagen en un búfer de píxeles en la memoria del navegador, luego la vuelve a codificar como jpeg / png / gif y luego la encapsula en un uri de datos que, con suerte, se almacena localmente. Si es así, significa que se han perdido todos los metadatos del archivo de imagen. Además, la recodificación de JPEG perderá algo de calidad y tendrá una relación calidad / número de bytes peor. Aún así, es bueno saberlo. Gracias por compartir.
Stéphane Gourichon
14

Un enfoque más moderno usando Promise y async / await:

toDataURL(url) {
    return fetch(url).then((response) => {
            return response.blob();
        }).then(blob => {
            return URL.createObjectURL(blob);
        });
}

luego

async download() {
        const a = document.createElement("a");
        a.href = await toDataURL("https://cdn1.iconfinder.com/data/icons/ninja-things-1/1772/ninja-simple-512.png");
        a.download = "myImage.png";
        document.body.appendChild(a);
        a.click();
        document.body.removeChild(a);
}

Encuentre documentación aquí: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch

Emerica
fuente
13
var pom = document.createElement('a');
pom.setAttribute('href', 'data:application/octet-stream,' + encodeURIComponent(text));
pom.setAttribute('download', filename);
pom.style.display = 'none';
document.body.appendChild(pom);
pom.click();
document.body.removeChild(pom);     
Sadi
fuente
5
El navegador Safari no admite el atributo de descarga
Pranav Labhe
11

Ésta es una solución general a su problema. Pero hay una parte muy importante de que la extensión del archivo debe coincidir con su codificación. Y, por supuesto, ese parámetro de contenido de la función downlowadImage debe ser una cadena codificada en base64 de su imagen.

const clearUrl = url => url.replace(/^data:image\/\w+;base64,/, '');

const downloadImage = (name, content, type) => {
  var link = document.createElement('a');
  link.style = 'position: fixed; left -10000px;';
  link.href = `data:application/octet-stream;base64,${encodeURIComponent(content)}`;
  link.download = /\.\w+/.test(name) ? name : `${name}.${type}`;

  document.body.appendChild(link);
  link.click();
  document.body.removeChild(link);
}

['png', 'jpg', 'gif'].forEach(type => {
  var download = document.querySelector(`#${type}`);
  download.addEventListener('click', function() {
    var img = document.querySelector('#img');

    downloadImage('myImage', clearUrl(img.src), type);
  });
});
a gif image: <image id="img" src="data:image/gif;base64,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" />


<button id="png">Download PNG</button>
<button id="jpg">Download JPG</button>
<button id="gif">Download GIF</button>

hakobpogh
fuente
3
Agregue una breve explicación a su respuesta, para que sea relevante para la persona que la preguntó
EDAD
1
link.href = 'data: application / octet-stream,' + encodeURIComponent (dirección) esto corrompe el archivo y por lo tanto no se puede abrir, canu sugiere por qué es así
OM The Eternity
Sí, ¡esta respuesta merece ser la mejor! La parte que me faltaba era la "cleanUrl", que generaba datos mal formados y rompía el archivo.
Iulian Pinzaru
2

Prueba esto:

<a class="button" href="http://www.glamquotes.com/wp-content/uploads/2011/11/smile.jpg" download="smile.jpg">Download image</a>
Muhammad Awais
fuente
2

En 2020 utilizo Blob para hacer una copia local de la imagen, que el navegador descargará como un archivo. Puedes probarlo en este sitio .

ingrese la descripción de la imagen aquí

(function(global) {
  const next = () => document.querySelector('.search-pagination__button-text').click();
  const uuid = () => Math.random().toString(36).substring(7);
  const toBlob = (src) => new Promise((res) => {
    const img = document.createElement('img');
    const c = document.createElement("canvas");
    const ctx = c.getContext("2d");
    img.onload = ({target}) => {
      c.width = target.naturalWidth;
      c.height = target.naturalHeight;
      ctx.drawImage(target, 0, 0);
      c.toBlob((b) => res(b), "image/jpeg", 0.75);
    };
    img.crossOrigin = "";
    img.src = src;
  });
  const save = (blob, name = 'image.png') => {
    const a = document.createElement("a");
    a.href = URL.createObjectURL(blob);
    a.target = '_blank';
    a.download = name;
    a.click();
  };
  global.download = () => document.querySelectorAll('.search-content__gallery-results figure > img[src]').forEach(async ({src}) => save(await toBlob(src), `${uuid()}.png`));
  global.next = () => next();
})(window);
Petr Tripolsky
fuente
Parece que este código decodifica la imagen en un búfer de píxeles (lienzo) en la memoria del navegador, luego la vuelve a codificar como jpeg / png / gif y luego la encapsula en un uri de datos que, con suerte, se almacena localmente. Si es así, significa que se han perdido todos los metadatos del archivo de imagen. Además, la recodificación de JPEG perderá algo de calidad y tendrá una relación calidad / número de bytes peor. Aún así, es bueno saberlo. Gracias por compartir.
Stéphane Gourichon
0
<html>
<head>
<script type="text/javascript">
function prepHref(linkElement) {
    var myDiv = document.getElementById('Div_contain_image');
    var myImage = myDiv.children[0];
    linkElement.href = myImage.src;
}
</script>
</head>
<body>
<div id="Div_contain_image"><img src="YourImage.jpg" alt='MyImage'></div>
<a href="#" onclick="prepHref(this)" download>Click here to download image</a>
</body>
</html>
Engr Zardari
fuente
0

Puede descargar este archivo directamente usando una etiqueta de anclaje sin mucho código.
Copie el fragmento y péguelo en su editor de texto y pruébelo ...!

<html>
<head>
</head>
<body>
   <div>
     <img src="https://upload.wikimedia.org/wikipedia/commons/1/1f/SMirC-thumbsup.svg" width="200" height="200">
      <a href="#" download="https://upload.wikimedia.org/wikipedia/commons/1/1f/SMirC-thumbsup.svg"> Download Image </a>
   </div>
</body>
</html>

vinod
fuente
2
agregue más detalles, por ejemplo, dónde se puede usar este código.
Maciej S.
-2

¿Qué pasa con el uso de la función .click () y la etiqueta?

(Versión comprimida)

<a id="downloadtag" href="examplefolder/testfile.txt" hidden download></a>

<button onclick="document.getElementById('downloadtag').click()">Download</button>

Ahora puedes activarlo con js. ¡Tampoco abre, como otros ejemplos, archivos de imagen y texto!

(versión de función js)

function download(){
document.getElementById('downloadtag').click();
}
<!-- HTML -->
<button onclick="download()">Download</button>
<a id="downloadtag" href="coolimages/awsome.png" hidden download></a>

Susurro venenoso
fuente
-5

encontre eso

<a href="link/to/My_Image_File.jpeg" download>Download Image File</a>

no funcionó para mí. No estoy seguro de por qué.

Descubrí que puede incluir un ?download=trueparámetro al final de su enlace para forzar una descarga. Creo que noté que Google Drive utiliza esta técnica.

En su enlace, incluya ?download=trueal final de su href.

También puede utilizar esta técnica para establecer el nombre del archivo al mismo tiempo.

En su enlace, incluya ?download=true&filename=My_Image_File.jpegal final de su href.

Mufasa
fuente
2
? download = true se pasa a Google Drive para decirle a su servidor que envíe el encabezado correcto para descargar la imagen. No es algo que funcione en ningún otro entorno a menos que se configure específicamente de esa manera.
muncherelli
-15

No necesita escribir js para hacer eso, simplemente use:

<a href="path_to/image.jpg" alt="something">Download image</a>

Y el propio navegador descargará automáticamente la imagen.

Si por alguna razón no funciona, agregue el atributo de descarga. Con este atributo puede establecer un nombre para el archivo descargable:

<a href="path_to/image.jpg" download="myImage">Download image</a>
António Regadas
fuente
Un enlace a la imagen solo abrirá la imagen en la misma ventana, a menos que su navegador esté configurado de manera diferente. El downloadatributo no es compatible con todos los navegadores.
Diseño de Adrian