Como acionar um download de arquivo ao clicar em um botão HTML ou JavaScript


434

Isso é loucura, mas não sei como fazer isso, e por causa de quão comuns são as palavras, é difícil encontrar o que eu preciso nos mecanismos de busca. Estou pensando que isso deve ser fácil de responder.

Eu quero um download de arquivo simples, que faria o mesmo que este:

<a href="file.doc">Download!</a>

Mas eu quero usar um botão HTML, por exemplo, um destes:

<input type="button" value="Download!">
<button>Download!</button>

Da mesma forma, é possível acionar um simples download via JavaScript?

$("#fileRequest").click(function(){ /* code to download? */ });

Definitivamente, não estou procurando uma maneira de criar uma âncora parecida com um botão, usar scripts de back-end ou mexer nos cabeçalhos do servidor ou nos tipos MIME.


15
Graças a você, "como acionar um download de arquivo em javascript" daria respostas muito mais rápidas para qualquer pesquisador futuro.
Danubian Sailor

Respostas:


278

Para o botão você pode fazer

<form method="get" action="file.doc">
   <button type="submit">Download!</button>
</form>

Você pode salvar a tag do formulário e apenas adicionar um clique na tag do botão.
Florian Leitgeb 23/01

12
não funciona como acionador, basta redirecionar para o URL como tag 'a'.
fdrv

7
Isso funciona melhor: <a href="path_to_file" download="proposed_file_name"> Download </a>
kscius 07/07/16

11
@kscius ainda hoje o atributo de download não é suportado no IE 11 (agora é suportado no Edge) e não é suportado no Safari. Em 2012, quando a resposta foi postada originalmente, ela não era suportada em nenhum navegador principal.
Cfreak #

1
qual é a diferença entre ter uma âncora com estilo de botão e ter um formulário com um botão?
Andrei Epure 23/02

444

Você pode acionar um download com o downloadatributo HTML5 .

<a href="path_to_file" download="proposed_file_name">Download</a>

Onde:

  • path_to_fileé um caminho que resolve para um URL na mesma origem . Isso significa que a página e o arquivo devem compartilhar o mesmo domínio, subdomínio, protocolo (HTTP vs. HTTPS) e porta (se especificado). As exceções são blob:e data:(que sempre funcionam) e file:(que nunca funcionam).
  • proposed_file_nameé o nome do arquivo no qual salvar. Se estiver em branco, o navegador usará como padrão o nome do arquivo.

Documentação: MDN , HTML Standard no download , HTML Standard nodownload , CanIUse


37
Não funciona com o Safari e certas versões do IE
Mohamed Hussain

4
Usar uma combinação de downloade target="_blank"parece ser suficiente para cobrir a maioria dos casos de uso. Os navegadores que entendem o downloadtratam como um download, caso contrário, ele é aberto em uma nova guia.
MK10 16/01

10
Como isso pode ser aplicado a um objeto de botão em vez de apenas a uma tag ?
storm_m2138

8
Na verdade, isso funciona apenas para URLs da mesma origem, conforme mencionado nos documentos MDN. Esta é uma enorme limitação se nós estamos olhando para desenvolver uma solução genérica
Akshat Gupta

6
A questão está pedindo explicitamente para usar um botão em vez de um link
Quentin

86

HTML:

<button type="submit" onclick="window.open('file.doc')">Download!</button>

8
Melhor e mais limpa solução. Mas você não precisa de nenhum Javascript extra aqui. A parte HTML com o onclick é suficiente.
Florian Leitgeb 23/01

4
E se eu quiser baixar um arquivo xml?
G07kore 12/05

2
Obrigado pelo seu código. Eu testei, ele pode trabalhar no IE, Chrome, Firefox.
Mshukumar # 22/16

6
Se você tiver um arquivo aceitável pelo navegador como um PDF, ele será aberto em uma nova guia para exibir a caixa de diálogo de download.
WindRider

1
window.open pode desencadear o bloqueio de pop-ups em um navegador e, portanto, não é recomendado. Você pode usar window.location = 'path', embora isso vá para o local na mesma janela do navegador.
Elendurwen 6/12/19

68

Com jQuery:

$("#fileRequest").click(function() {
    // // hope the server sets Content-Disposition: attachment!
    window.location = 'file.doc';
});

1
Perfeito, obrigado. Você sabe se a maioria dos servidores definirá a disposição de conteúdo como 'anexo' por padrão?
Brentonstrine

5
Não há "mais". Depende completamente. Não confie na definição.
Matt Bola

3
Esse problema está me deixando balístico, e essa foi a única opção que funcionou (e é suportada pelo IE). Vou adicionar para qualquer n00bs como eu que para definir a Disposição de Conteúdo, tudo o que você precisa fazer é: <? Php header ('Disposição de Conteúdo: anexo; filename = "filename.here"'); ?>
user124384

3
Sem jquery. Período.
Adam Arold

1
Este trabalho fazes, se você está tentando baixar uma imagem, ela iria abrir a imagem no navegador
Dheeraj

34

Tópico antigo, mas está faltando uma solução js simples:

let a = document.createElement('a')
a.href = item.url
a.download = item.url.split('/').pop()
document.body.appendChild(a)
a.click()
document.body.removeChild(a)

24
@NicholasKyriakides tipo de lembra-me de esta jóia: image.ibb.co/dtkUWJ/Selection_002.png
Stefanos Chrs

@BryanLarsen qual versão do FF?
Stefanos Chrs

1
@BryanLarsen Você está certo, o Firefox não permite isso sem adicionar o elemento ao corpo primeiro. Obrigado, atualizando a resposta
Stefanos Chrs 19/02/19

1
Existe uma maneira de a função javascript ser acionada quando o download terminar? Apenas tentando mostrar uma mensagem quando o download iniciar e remover a mensagem quando o download for concluído.
mohit bansal

1
@mohitbansal (un), felizmente, não como é no nível do navegador
Stefanos Chrs

23

Você pode fazer isso com "truque" com iframe invisível. Quando você define "src", o navegador reage como se você clicasse em um link com o mesmo "href". Ao contrário da solução com forma, ele permite incorporar lógica adicional, por exemplo, ativar o download após o tempo limite, quando algumas condições são atendidas etc.

Também é muito silencioso, não há novas janelas / abas piscando como no uso window.open.

HTML:

<iframe id="invisible" style="display:none;"></iframe>

Javascript:

function download() {
    var iframe = document.getElementById('invisible');
    iframe.src = "file.doc";
}

Sim, pelo menos se você realmente aprovar o iframe para document.body.
Yxhuvud 27/05

1
No momento, isso não parece estar funcionando no Chrome, embora funcionasse. Gostaria de saber se meio que para de funcionar intermitentemente em diferentes versões do Chrome.
Dobes Vandermeer

Funciona no Chrome a partir da versão 61.0.3163.100 (Compilação oficial) (64 bits)
AndrewBenjamin

Não funciona com imagens no Firefox v57. Apenas renderiza a imagem no iframe.
Antony

15

Versão do Bootstrap

<a class="btn btn-danger" role="button" href="path_to_file"
   download="proposed_file_name">
  Download
</a>

Documentado nos documentos do Bootstrap 4 e funciona também no Bootstrap 3.


9
A única coisa que isso tem a ver com o Bootstrap são os nomes das classes, é apenas o poder do HTML5.
Machado

3
A questão é perguntar explicitamente como fazer isso com um botão em vez de um link.
Quentin

2
se você soubesse alguma coisa sobre bootstrap, veria que é um botão.
John Lord

11

Eu acho que essa é a solução que você estava procurando

<button type="submit" onclick="window.location.href='file.doc'">Download!</button>

Eu tive um caso em que meu Javascript gerou um arquivo CSV. Como não há URL remota para fazer o download, uso a seguinte implementação.

downloadCSV: function(data){
    var MIME_TYPE = "text/csv";

    var blob = new Blob([data], {type: MIME_TYPE});
    window.location.href = window.URL.createObjectURL(blob);
}

em 404 -> mudança de página para uma página de erro 404. mesmo problema indicado nas outras location.hrefsoluções.
precisa saber é o seguinte

9

A respeito:

<input type="button" value="Download Now!" onclick="window.location = 'file.doc';">

5
Isso não funciona, se o seu arquivo, por exemplo, for uma imagem, pois seria apenas aberto no navegador.
camião articulado

Outro problema ocorre que é se o arquivo está faltando ele navega a página inteira para uma página 404
Hugheth

7

Você pode ocultar o link de download e clicar no botão.

<button onclick="document.getElementById('link').click()">Download!</button>
<a id="link" href="file.doc" download hidden></a>

Para que isso funcione no Firefox, o recurso deve estar no mesmo domínio que o documento. Definir cabeçalhos CORS não ajuda.
Antony

2
Nunca mais faça isso
Wannes

@Wannes porque não?
Starwarswii

4

Se você está procurando uma solução de baunilha JavaScript (sem jQuery) e sem usar o atributo HTML5, pode tentar isso.

const download = document.getElementById("fileRequest");

download.addEventListener('click', request);

function request() {
    window.location = 'document.docx';
}
.dwnld-cta {
    border-radius: 15px 15px;
    width: 100px;
    line-height: 22px
}
<h1>Download File</h1>
<button id="fileRequest" class="dwnld-cta">Download</button>


1

Foi o que finalmente funcionou para mim, uma vez que o arquivo a ser baixado foi determinado quando a página é carregada.

JS para atualizar o atributo de ação do formulário:

function setFormAction() {
    document.getElementById("myDownloadButtonForm").action = //some code to get the filename;
}

Chamando JS para atualizar o atributo de ação do formulário:

<body onLoad="setFormAction();">

Etiqueta de formulário com o botão enviar:

<form method="get" id="myDownloadButtonForm" action="">
    Click to open document:  
    <button type="submit">Open Document</button>
</form>

O seguinte NÃO funcionou:

<form method="get" id="myDownloadButtonForm" action="javascript:someFunctionToReturnFileName();">

provavelmente porque se você tiver o arquivo no tempo de carregamento, não poderá simplesmente executar a ação no servidor usando um mecanismo de modelo? por que a necessidade de código js?
Andrei Epure 23/02

1

Se você não pode usar o formulário, outra abordagem com o downloadjs é adequada. O Downloadjs usa a API de arquivos blob e html 5 sob o capô:

{downloadjs (url, nome do arquivo)}) />

* é sintaxe jsx / react, mas pode ser usado em html puro


Para evitar problemas de CORS para imagens em outros domínios, coloque crossorigin = "anonymous" na tag img, da seguinte forma: <img src = "image.png" crossorigin = "anonymous" />
Jonathan Harris

0

Em qualquer lugar entre as tags <body>e e </body>, coloque um botão usando o código abaixo:

<button>
    <a href="file.doc" download>Click to Download!</a>
</button>

Isso com certeza funcionará!


1
Para Chrome é uma grande solução
Hayk Aramyan

1
Não funciona no Safari ou: W3 Escolas
Alex

2
Não funcionar nos navegadores MS é um grande problema, e nem sempre o Chrome será a resposta.
SudoKid

Você não pode colocar um link dentro de um botão em HTML
Quentin

0

Outra maneira de fazer, caso você tenha um URL complexo, como file.doc?foo=bar&jon=doeadicionar campo oculto ao formulário

<form method="get" action="file.doc">
  <input type="hidden" name="foo" value="bar" />
  <input type="hidden" name="john" value="doe" />
  <button type="submit">Download Now</button>
</form>

inspirado na resposta @Cfreak que não está completa


0

você pode adicionar tags sem nenhum texto, mas com o link. e quando você clicar no botão como no código, basta executar a função $ ("yourlinkclass"). click ().


-1

atributo de download faça

 <a class="btn btn-success btn-sm" href="/file_path/file.type" download>
     <span>download </span>&nbsp;<i class="fa fa-download"></i>
 </a>

2
Eu gosto da sua resposta
George C.

2
A questão é perguntar explicitamente como fazer isso com um botão em vez de um link.
Quentin

-6

Se você usar a <a>tag, não se esqueça de usar o URL inteiro que leva ao arquivo - ou seja:

<a href="http://www.example.com/folder1/file.doc">Download</a>

Eu não acho que esse seja o problema aqui. Além disso, o caminho "absoluto" não é necessário se o link estiver no mesmo caminho que o arquivo.
Rocket Hazmat

@Rocket - você está, é claro, correto sobre o caminho absoluto; no entanto, é a melhor maneira de garantir que ele esteja certo. Deixarei ao OP decidir se foi útil - #
237 Mark Mark

A questão é perguntar explicitamente como fazer isso com um botão em vez de um link.
Quentin

o atributo de download está ausente nesta solução. Mesmo depois de adicionar atributos de download, ele não funcionará em vários domínios.
S sharif

-6

Para mim, adicionar um botão ao invés de um texto âncora funciona muito bem.

<a href="file.doc"><button>Download!</button></a>

Pode não ser bom para a maioria das regras, mas parece muito bom.


5
Isso funciona apenas porque o seu navegador não suporta arquivos .doc.
Design by Adrian

Seu HTML é inválido. <a>elementos não podem conter <button>elementos.
Quentin

sempre foi assim? Esta resposta tinha dois anos quando você comentou isso.
John Lord
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.