Baixar arquivo usando Javascript/jQuery

Tenho um requisito muito semelhante especificado aqui.

Eu preciso que o usuário's browser inicie um download manualmente quando $('a#someID').click();

Mas eu não posso utilizar o método window.href, já que ele substitui o conteúdo da página atual pelo arquivo que você'está tentando baixar.

Em vez disso, quero abrir o download em uma nova janela/tab. Como isso é possível?

Solução

Utilize um &lt invisível;iframe>:


<script>
function Download(url) {
    document.getElementById('my_iframe').src = url;
};
</script>

Para forçar o navegador a baixar um arquivo que ele seria capaz de renderizar (como arquivos HTML ou texto), você precisa que o servidor defina o arquivo's MIME Type para um valor sem sentido, como application/x-please-download-me ou, alternativamente, application/octet-stream, que é utilizado para dados binários arbitrários.

Se você quiser abri-lo apenas em uma nova aba, a única maneira de fazer isso é o usuário clicar em um link com o atributo target definido como _blank.

In jQuery:

$('a#someID').attr({target: '_blank', 
                    href  : 'http://localhost/directory/file.pdf'});

Sempre que esse link for clicado, ele irá baixar o arquivo em uma nova aba/janela.

Comentários (21)

**2019 actualização dos browsers modernos***

Esta é a abordagem I'd agora recomendo com algumas advertências:

  • É necessário um navegador relativamente moderno
  • Se se espera que o arquivo seja **muito grande*** você deve provavelmente fazer algo similar à abordagem original (iframe e cookie) porque algumas das operações abaixo podem provavelmente consumir memória do sistema pelo menos tão grande quanto o arquivo sendo baixado e/ou outros efeitos colaterais interessantes da CPU.
fetch('https://jsonplaceholder.typicode.com/todos/1')
  .then(resp => resp.blob())
  .then(blob => {
    const url = window.URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.style.display = 'none';
    a.href = url;
    // the filename you want
    a.download = 'todo-1.json';
    document.body.appendChild(a);
    a.click();
    window.URL.revokeObjectURL(url);
    alert('your file has downloaded!'); // or you know, something with better UX...
  })
  .catch(() => alert('oh no!'));

**2012 original jQuery/iframe/cookie abordagem baseada em jQuery/iframe/cookie***

Eu criei o plugin jQuery File Download (Demo) (GitHub) que também pode ajudar na sua situação. Ele funciona muito similar com um iframe, mas tem algumas características legais que eu achei bastante úteis:

  • Muito fácil de configurar com bons visuais (jQuery UI Dialog, mas não é necessário), tudo é testado também

  • O usuário nunca sai da mesma página de onde iniciou o download de um arquivo. Esta característica está a tornar-se crucial para as aplicações web modernas

  • funções successCallback e failCallback permitem que você seja explícito sobre o que o usuário vê em qualquer uma das situações

  • Em conjunto com o jQuery UI um desenvolvedor pode facilmente mostrar um modal dizendo ao usuário que um download de arquivo está ocorrendo, desmarcar o modal após o início do download ou mesmo informar ao usuário de uma maneira amigável que um erro ocorreu. Veja a Demo para um exemplo disto. Espero que isto ajude alguém!

Aqui está uma demonstração de caso de uso simples usando o plugin fonte com promessas. A página demo inclui muitos outros, 'melhor UX' exemplos também.

$.fileDownload('some/file.pdf')
    .done(function () { alert('File download a success!'); })
    .fail(function () { alert('File download failed!'); });
Comentários (10)

Se você já está usando jQuery, você poderia aproveitar para produzir um pequeno snippet Uma versão jQuery da resposta de Andrew's:

var $idown;  // Keep it outside of the function, so it's initialized once.
downloadURL : function(url) {
  if ($idown) {
    $idown.attr('src',url);
  } else {
    $idown = $('<iframe>', { id:'idown', src:url }).hide().appendTo('body');
  }
},
//... How to use it:
downloadURL('http://whatever.com/file.pdf');
Comentários (7)