A maneira mais fácil de abrir uma janela de download sem navegar para fora da página

119

Qual é a melhor maneira entre navegadores de abrir uma caixa de diálogo de download (vamos supor que podemos definir a disposição de conteúdo: anexo nos cabeçalhos) sem navegar para fora da página atual ou abrir pop-ups, o que não funciona bem no Internet Explorer (IE ) 6.

mkoryak
fonte

Respostas:

106

7 anos se passaram e não sei se funciona para o IE6 ou não, mas isso mostra OpenFileDialog no FF e no Chrome.

var file_path = 'host/path/file.ext';
var a = document.createElement('A');
a.href = file_path;
a.download = file_path.substr(file_path.lastIndexOf('/') + 1);
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
0x000f
fonte
Primeiramente obrigado por esta solução, mas eu encontrei um bug se removeChild (a) o zip irá descompactar o erro com o zip quebrado, então remova este código resolva
Roy
2
@Manoj Rana - Verifiquei no FF 58.0.2 (64 bits) que está funcionando. Não funcionará em nenhum FF se você remover 2 linhas document.body.appendChild (a); document.body.removeChild (a);
0x000f
1
Para fazer funcionar no Edge 16, o cabeçalho, de onde vem o arquivo, deve conter Content-Type: application/octet-streame Content-Disposition: attachment.
Simon
12
isso não funciona mais developers.google.com/web/updates/2018/02/…
Paulius Dragunas
2
@ user1933131 Chrome remove apenas para origem cruzada
Brandy23
202

Este javascript é bom que não abre uma nova janela ou guia.

window.location.assign(url);
mozgras
fonte
18
É o mesmo que window.location = url; “Sempre que um novo valor é atribuído ao objeto de localização, um documento será carregado usando a URL como se window.location.assign () tivesse sido chamado com a URL modificada” - developer.mozilla.org/en-US/docs/ Web / API / window.location
Rob Juurlink
13
Isso faz com que a conexão WebSocket seja desconectada.
igorpavlov
4
Usei a mesma solução, mas ela abre o arquivo na mesma guia em vez de abrir uma caixa de diálogo de download.
Techno Cracker
2
é o mesmo para window.open (url, '_self') se a url for para a página de download.
especialista quer ser em
5
Ao usar o IE11, descobri que isso fazia com que o JS parasse. Então, para o IE 11, usei window.open (url, '_blank') que abriu outra guia, no entanto, essa guia fechou quando descobri que o arquivo era um download. Isso manteve o JS em execução.
Lucas,
23

Eu sempre adiciono um target = "_ blank" ao link de download. Isso abrirá uma nova janela, mas assim que o usuário clicar em salvar, a nova janela será fechada.

jao
fonte
2
Esta é a melhor resposta. No Internet Explorer, adicionar 'target = "_ blank"' a um link que deve ser baixado fará com que o navegador pare de navegar (onde "HTML1300: Navigation ocorreu" é impresso) e, portanto, pode deixar a página em um estado inconsistente.
user64141
23

Coloque isso na seção do cabeçalho HTML, definindo urlvar como o URL do arquivo a ser baixado:

<script type="text/javascript">  
function startDownload()  
{  
     var url='http://server/folder/file.ext';    
     window.open(url, 'Download');  
}  
</script>

Em seguida, coloque isso no corpo, que iniciará o download automaticamente após 5 segundos:

<script type="text/javascript">  
setTimeout('startDownload()', 5000); //starts download after 5 seconds  
</script> 

(A partir daqui .)

George Claghorn
fonte
2
isso não funciona, porque no IE6, se o usuário clicar em "salvar", o arquivo será salvo, mas o popup permanecerá aberto. Isto não é aceitável.
mkoryak
este código não está funcionando no safari, você pode me ajudar a resolver no safari, por favor.
Renish Khunt
17

Eu sei que a pergunta foi feita, 7 years and 9 months agomas muitas soluções postadas parecem não funcionar, por exemplo, usar um <iframe>funciona apenas com FireFoxe não funciona com Chrome.

Melhor solução:

Ao melhor solução de trabalho para abrir um pop-up de download de arquivoJavaScripté usar umHTMLelemento de link, sem a necessidade de anexar o elemento de link ao,document.body conforme declarado em outras respostas.

Você pode usar a seguinte função:

function downloadFile(filePath){
    var link=document.createElement('a');
    link.href = filePath;
    link.download = filePath.substr(filePath.lastIndexOf('/') + 1);
    link.click();
}

Em meu aplicativo, estou usando desta forma:

downloadFile('report/xls/myCustomReport.xlsx');

Demonstração de trabalho:

Nota:

  • Você deve usar o link.downloadatributo para que o navegador não abra o arquivo em uma nova guia e acione o pop-up de download.
  • Isso foi testado com vários tipos de arquivo (docx, xlsx, png, pdf, ...).
cнŝdk
fonte
Qual seria a melhor maneira de exibir um gif de carregamento até que o arquivo seja baixado?
Ctrl_Alt_Defeat
1
@Ctrl_Alt_Defeat Bem, neste caso, não será fácil para acompanhar o processo de download, mas um truque pode ser para mostrar esta animação gif no linkclique e escondê-lo depois de um tempo limite, usando este código: link.onclick = function() { document.body.innerText = "The file is being downloaded ..."; setTimeout(function() { document.body.innerText = ""; }, 2000); }, você pode vê-lo trabalhando no presente fiddle , mas tenha em mente que não é uma forma recomendada de fazê-lo, seria melhor manuseado se estivéssemos usando Ajax.
cнŝdk
1
não funciona no firefox. como baixar no firefox?
Manoj Rana
@ManojRana Para o firefox, você pode usar e iframever esta resposta .
cнŝdk
2
Esta solução funciona no Chrome, Safari e Firefox para mim :)
ariebear
15

Tenho procurado uma boa maneira de usar o javascript para iniciar o download de um arquivo, como esta pergunta sugere. No entanto, essas respostas não foram úteis. Em seguida, fiz alguns testes do xbrowser e descobri que um iframe funciona melhor em todos os navegadores modernos IE> 8.

downloadUrl = "http://example.com/download/file.zip";
var downloadFrame = document.createElement("iframe"); 
downloadFrame.setAttribute('src',downloadUrl);
downloadFrame.setAttribute('class',"screenReaderText"); 
document.body.appendChild(downloadFrame); 

class="screenReaderText" é minha classe para estilizar o conteúdo que está presente, mas não visível.

css:

.screenReaderText { 
  border: 0; 
  clip: rect(0 0 0 0); 
  height: 1px; 
  margin: -1px; 
  overflow: hidden; 
  padding: 0; 
  position: absolute; 
  width: 1px; 
}

igual a .visuallyHidden em html5boilerplate

Eu prefiro isso ao método javascript window.open porque se o link for quebrado, o método iframe simplesmente não faz nada ao invés de redirecionar para uma página em branco dizendo que o arquivo não pôde ser aberto.

window.open(downloadUrl, 'download_window', 'toolbar=0,location=no,directories=0,status=0,scrollbars=0,resizeable=0,width=1,height=1,top=0,left=0');
window.focus();
alockwood05
fonte
6

Usando a API HTML5 Blob Object-URL File:

/**
 * Save a text as file using HTML <a> temporary element and Blob
 * @see /programming/49988202/macos-webview-download-a-html5-blob-file
 * @param fileName String
 * @param fileContents String JSON String
 * @author Loreto Parisi
*/
var saveBlobAsFile = function(fileName,fileContents) {
    if(typeof(Blob)!='undefined') { // using Blob
        var textFileAsBlob = new Blob([fileContents], { type: 'text/plain' });
        var downloadLink = document.createElement("a");
        downloadLink.download = fileName;
        if (window.webkitURL != null) {
            downloadLink.href = window.webkitURL.createObjectURL(textFileAsBlob);
        }
        else {
            downloadLink.href = window.URL.createObjectURL(textFileAsBlob);
            downloadLink.onclick = document.body.removeChild(event.target);
            downloadLink.style.display = "none";
            document.body.appendChild(downloadLink);
        }
        downloadLink.click();
    } else {
        var pp = document.createElement('a');
        pp.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(fileContents));
        pp.setAttribute('download', fileName);
        pp.onclick = document.body.removeChild(event.target);
        pp.click();
    }
}//saveBlobAsFile

/**
 * Save a text as file using HTML <a> temporary element and Blob
 * @see /programming/49988202/macos-webview-download-a-html5-blob-file
 * @param fileName String
 * @param fileContents String JSON String
 * @author Loreto Parisi
 */
var saveBlobAsFile = function(fileName, fileContents) {
  if (typeof(Blob) != 'undefined') { // using Blob
    var textFileAsBlob = new Blob([fileContents], {
      type: 'text/plain'
    });
    var downloadLink = document.createElement("a");
    downloadLink.download = fileName;
    if (window.webkitURL != null) {
      downloadLink.href = window.webkitURL.createObjectURL(textFileAsBlob);
    } else {
      downloadLink.href = window.URL.createObjectURL(textFileAsBlob);
      downloadLink.onclick = document.body.removeChild(event.target);
      downloadLink.style.display = "none";
      document.body.appendChild(downloadLink);
    }
    downloadLink.click();
  } else {
    var pp = document.createElement('a');
    pp.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(fileContents));
    pp.setAttribute('download', fileName);
    pp.onclick = document.body.removeChild(event.target);
    pp.click();
  }
} //saveBlobAsFile

var jsonObject = {
  "name": "John",
  "age": 31,
  "city": "New York"
};
var fileContents = JSON.stringify(jsonObject, null, 2);
var fileName = "data.json";

saveBlobAsFile(fileName, fileContents)

Loretoparisi
fonte
2
Acho que esta é a melhor forma de o fazer !!
Kushal MK
1
Também é uma boa prática chamar URL.revokeObjectURL(url), quando o arquivo não for mais necessário para liberar memória
SleepWalker
5

Modificar a localização da janela pode causar alguns problemas, especialmente quando você tem uma conexão persistente como o websocket. Por isso, sempre recorro à boa e velha solução iframe.

HTML

<input type="button" onclick="downloadButtonClicked()" value="Download"/>
...
...
...
<iframe style="display:none;" name="hiddenIframe" id="hiddenIframe"></iframe>

Javascript

function downloadButtonClicked() {
    // Simulate a link click
    var url = 'your_download_url_here';
    var elem = document.createElement('a');
    elem.href = url;
    elem.target = 'hiddenIframe';
    elem.click();
}
Bnrdo
fonte
5

Se o link for para um url de arquivo válido, simplesmente atribuir window.location.href funcionará.

No entanto, às vezes o link não é válido e um iframe é necessário.

Faça seu event.preventDefault normal para evitar que a janela seja aberta e, se você estiver usando jQuery, isso funcionará:

$('<iframe>').attr('src', downloadThing.attr('href')).appendTo('body').on("load", function() {
   $(this).remove();
});
TaylorMac
fonte
2

Depois de horas de tentativas, a função nasceu :) Tive um cenário em que tive que exibir o carregador a tempo enquanto o arquivo se preparava para download:

Trabalhando no Chrome, Safari e Firefox

function ajaxDownload(url, filename = 'file', method = 'get', data = {}, callbackSuccess = () => {}, callbackFail = () => {}) {
    $.ajax({
        url: url,
        method: 'GET',
        xhrFields: {
            responseType: 'blob'
        },
        success: function (data) {
            // create link element
            let a = document.createElement('a'), 
                url = window.URL.createObjectURL(data);

            // initialize 
            a.href = url;
            a.download = filename;

            // append element to the body, 
            // a must, due to Firefox
            document.body.appendChild(a);

            // trigger download
            a.click();

            // delay a bit deletion of the element
            setTimeout(function(){
                window.URL.revokeObjectURL(url);
                document.body.removeChild(a);
            }, 100);

            // invoke callback if any 
            callbackSuccess(data);
        },
        error: function (err) {
            // invoke fail callback if any
            callbackFail(err)
        }
    });
М.Б.
fonte
0

E se:

<meta http-equiv="refresh" content="5;url=http://site.com/file.ext">

Desta forma funciona em todos os navegadores (eu acho) e permite colocar uma mensagem como: "Se o download não começar em cinco segundos, clique aqui."

Se precisar que seja com javascript .. bem ...

document.write('<meta http-equiv="refresh" content="5;url=http://site.com/file.ext">');

Saudações


fonte
0

Um iframe pequeno / oculto pode funcionar para essa finalidade.

Dessa forma, você não precisa se preocupar em fechar o pop-up.

Simon
fonte