Força o navegador a baixar arquivos de imagem com um clique

100

Preciso que o navegador baixe os arquivos de imagem exatamente como faz ao clicar em uma planilha do Excel.

Existe uma maneira de fazer isso usando apenas a programação do lado do 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>

Como deve funcionar em caso de download de uma planilha do Excel (o que os navegadores fazem)?

Amit
fonte
7
O downloadatributo.
Šime Vidas
6
A melhor maneira de garantir o download de um arquivo é definir a disposição do conteúdo no lado do servidor, a maioria das soluções do lado do cliente não são tão confiáveis.
adeneo
1
Possível duplicata: stackoverflow.com/questions/2408146/… ?
Karl-André Gagnon
Há uma pergunta semelhante que já foi respondida para você: stackoverflow.com/a/6799284/1948211
dschu
Karl-Andre Gagnon: Por favor, vá direto ao assunto. [Eu não marquei HTML 5 porque não quero usá-lo] e sem tocar no servidor
Amit

Respostas:

172

Usando HTML5 você pode adicionar o atributo 'download' aos seus links.

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

Os navegadores compatíveis solicitarão o download da imagem com o mesmo nome de arquivo (neste exemplo, image.png).

Se você especificar um valor para este atributo, ele se tornará o novo nome de arquivo:

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

ATUALIZAÇÃO: a partir da primavera de 2018, isso não é mais possível para hrefs de origem cruzada . Portanto, se você deseja criar <a href="https://i.imgur.com/IskAzqA.jpg" download>em um domínio diferente de imgur.com, não funcionará como esperado. Anúncio de suspensão de uso e remoções do Chrome

Richard Parnaby-King
fonte
Richard Parnaby-King: Usar o atributo HTML 5 pode ser feito, mas preciso fazê-lo SEM usar HTML5 ou qualquer ferramenta SERVER SIDE (se for possível) Obrigado pelos ajudantes :)
Amit
2
Ainda não é totalmente compatível com todos os navegadores, mas é uma boa solução se você não se importa com o IE ou Safari. caniuse.com/#feat=download
stacigh
Obrigado, por uma solução HTML5. Como ainda permitir 'salvar como' que me permite inserir um nome de arquivo antes de salvar?
teleman
Não posso controlar onde este arquivo deve ser baixado? Ele apenas baixa para baixar a pasta diretamente. Eu quero que ele use o caminho local do arquivo html.
Arjun Chiddarwar
1
@ArjunChiddarwar Não, isso abre vulnerabilidades de segurança (imagine alguém salvando um arquivo malicioso diretamente em sua pasta do Windows). O caminho de download é baseado nas configurações do navegador - por exemplo, por padrão, o Chrome fará o download para sua pasta de downloads.
Richard Parnaby-King
96

Eu consegui fazer isso funcionar no Chrome e Firefox também anexando um link para o documento.

var link = document.createElement('a');
link.href = 'images.jpg';
link.download = 'Download.jpg';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
DrowsySaturn
fonte
2
Esta é realmente uma solução muito boa para aplicativos da web em que o Javascript está em todo lugar. Porém, funciona apenas no Google Chrome (em minha configuração de teste).
Pavel
Alguma ideia sobre uma maneira de testar a compatibilidade? Eu gostaria de usar esta técnica, mas também preciso oferecer suporte a outros navegadores, então precisaria oferecer uma alternativa (como abrir PDF em uma nova janela ou um link para download) quando isso não for compatível. Alguém teve sorte com isso?
alexrussell
13
Ótima solução, obrigado! Observe que, se você omitir document.body.appendChild(link), não funcionará no firefox. Também é bom remover o elemento criado com document.body.removeChild(link);afterlink.click()
akn
8
melhor solução. Para evitar lixo no uso de DOMsetTimeout( function () { link.parentNode.removeChild( link ); },10 );
Mephiztopheles
1
Obrigado deveria ter sido a resposta selecionada desde a pergunta feita como fazê-lo no JAVASCRIPT.
codehelp4
33

Leeroy e Richard Parnaby-King:

ATUALIZAÇÃO: a partir da primavera de 2018, isso não é mais possível para hrefs de origem cruzada. Portanto, se você deseja criar em um domínio diferente de imgur.com, não funcionará como esperado. Anúncio de suspensão de uso e remoções do 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();
}
iXs
fonte
2
download de imagem, mas não abre, pois está declarado 'Imagem está quebrada'
picacode
19

Atualização da primavera de 2018

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

Embora ainda seja compatível, a partir de fevereiro de 2018, o chrome desativou esse recurso para download de origem cruzada, o que significa que isso só funcionará se o arquivo estiver localizado no mesmo nome de domínio.

Eu descobri uma solução alternativa para baixar imagens entre domínios após a nova atualização do Chrome que desabilitou o download entre domínios. Você pode modificar isso em uma função para atender às suas necessidades. Você pode conseguir obter o tipo de imagem mime (jpeg, png, gif, etc) com mais pesquisas, se necessário. Pode haver uma maneira de fazer algo semelhante a isso com os vídeos também. Espero que isso ajude alguém!

Leeroy e Richard Parnaby-King:

ATUALIZAÇÃO: a partir da primavera de 2018, isso não é mais possível para hrefs de origem cruzada. Portanto, se você deseja criar em um domínio diferente de imgur.com, não funcionará como esperado. Anúncio de suspensão de uso e remoções do 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
fonte
Parece que este código decodifica a imagem em um buffer de pixels na memória do navegador, então a reencodifica como jpeg / png / gif e então encapsula isso em um uri de dados que é então armazenado localmente. Nesse caso, significa que todos os metadados do arquivo de imagem foram perdidos. Além disso, a recodificação de JPEG perderá alguma qualidade e terá uma relação qualidade / contagem de bytes pior. Mesmo assim, é bom saber. Obrigado por compartilhar.
Stéphane Gourichon
14

Uma abordagem mais moderna usando Promise e async / await:

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

então

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

Encontre a documentação aqui: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch

Emerica
fonte
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
fonte
5
O navegador safari não suporta o atributo de download
Pranav Labhe
11

Esta é uma solução geral para o seu problema. Mas há uma parte muito importante que a extensão do arquivo deve corresponder à sua codificação. E, claro, esse parâmetro de conteúdo da função downlowadImage deve ser uma string codificada em base64 de sua imagem.

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
fonte
3
Adicione uma breve explicação à sua resposta para torná-la relevante para a pessoa que a fez a pergunta
IDADE
1
link.href = 'data: application / octet-stream,' + encodeURIComponent (endereço) isso corrompe o arquivo e, portanto, não pode ser aberto, posso sugerir o porquê
OM The Eternity
Sim, essa resposta merece ser a melhor! A parte que faltava para mim era o "cleanUrl", que estava gerando dados malformados e quebrando o arquivo.
Iulian Pinzaru
3

Em 2020, eu uso o Blob para fazer uma cópia local da imagem, cujo navegador fará o download como um arquivo. Você pode testá-lo neste site .

insira a descrição da imagem aqui

(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
fonte
Parece que este código decodifica a imagem em um buffer de pixels (canvas) na memória do navegador, então a reencodifica como jpeg / png / gif e então encapsula em um uri de dados que é então armazenado localmente. Nesse caso, significa que todos os metadados do arquivo de imagem foram perdidos. Além disso, a recodificação de JPEG perderá alguma qualidade e terá uma relação qualidade / contagem de bytes pior. Mesmo assim, é bom saber. Obrigado por compartilhar.
Stéphane Gourichon
2

Experimente isto:

<a class="button" href="http://www.glamquotes.com/wp-content/uploads/2011/11/smile.jpg" download="smile.jpg">Download image</a>
Muhammad Awais
fonte
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
fonte
0

Você pode baixar este arquivo diretamente usando a tag âncora sem muito código.
Copie o snippet e cole em seu editor de texto e experimente ...!

<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
fonte
2
adicione mais detalhes, por exemplo, onde este código pode ser usado.
Maciej S.
-2

Que tal usar a função .click () e a tag?

(Versão comprimida)

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

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

Agora você pode acioná-lo com js. Também não abre, como em outros exemplos, arquivos de imagem e texto!

(versão da função js)

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

Sussurro Venenoso
fonte
-5

eu achei aquilo

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

não funcionou para mim. Não sei por quê.

Eu descobri que você pode incluir um ?download=true parâmetro no final do seu link para forçar um download. Acho que percebi essa técnica sendo usada pelo Google Drive.

Em seu link, inclua ?download=trueno final de seu href.

Você também pode usar esta técnica para definir o nome do arquivo ao mesmo tempo.

Em seu link, inclua ?download=true&filename=My_Image_File.jpegno final de seu href.

Mufasa
fonte
2
? download = true é passado ao Google Drive para informar ao servidor para enviar o cabeçalho correto para baixar a imagem. Não é algo que funcionaria em qualquer outro ambiente, a menos que fosse especificamente configurado dessa forma.
muncherelli de
-15

Você não precisa escrever js para fazer isso, basta usar:

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

E o próprio navegador fará o download da imagem automaticamente.

Se por algum motivo não funcionar, adicione o atributo de download. Com este atributo, você pode definir um nome para o arquivo para download:

<a href="path_to/image.jpg" download="myImage">Download image</a>
António Regadas
fonte
Um link para a imagem só abrirá a imagem na mesma janela, a menos que seu navegador esteja configurado de forma diferente. O downloadatributo não é compatível com todos os navegadores.
Design de Adrian