Il modo più semplice per aprire una finestra di download senza dover uscire dalla pagina


119

Qual è il miglior modo cross browser per aprire una finestra di dialogo di download (supponiamo di poter impostare la disposizione del contenuto: allegato nelle intestazioni) senza uscire dalla pagina corrente o aprire popup, che non funziona bene in Internet Explorer (IE ) 6.

Risposte:


106

Sono passati 7 anni e non so se funziona o meno per IE6, ma questo richiede OpenFileDialog in FF e 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);

Innanzitutto grazie per questa soluzione, ma ho trovato un bug se removeChild (a) lo zip decomprimerà l'errore con zip è rotto, quindi rimuovi questo codice risolvilo
Roy

2
@Manoj Rana - Ho verificato che FF 58.0.2 (64 bit) funzioni. Non funzionerà su alcun FF se rimuovi 2 righe document.body.appendChild (a); document.body.removeChild (a);
0x000f

1
Per farlo funzionare su Edge 16, l'intestazione, da cui proviene il file, dovrebbe contenere Content-Type: application/octet-streame Content-Disposition: attachment.
Simon


2
@ user1933131 chrome rimuove solo per cross-origin
Brandy23

202

Questo javascript è bello perché non apre una nuova finestra o scheda.

window.location.assign(url);

18
È lo stesso di window.location = url; "Ogni volta che viene assegnato un nuovo valore all'oggetto location, un documento verrà caricato utilizzando l'URL come se window.location.assign () fosse stato chiamato con l'URL modificato" - developer.mozilla.org/en-US/docs/ Web / API / window.location
Rob Juurlink

13
Ciò causa la disconnessione della connessione WebSocket.
igorpavlov

4
Ho usato la stessa soluzione ma apre il file nella stessa scheda invece di aprire una finestra di dialogo di download.
Techno Cracker

2
è lo stesso di window.open (url, '_self') se l'URL è per la pagina di download allora.
esperto vuole essere l'

5
Quando si utilizza IE11, ho riscontrato che ciò causava l'arresto di JS. Quindi per IE 11 ho usato window.open (url, '_blank') che ha aperto un'altra scheda, tuttavia quella scheda si è chiusa quando ha funzionato il file era un download. Ciò ha mantenuto il JS in esecuzione.
Luca

23

Aggiungo sempre un target = "_ blank" al link per il download. Si aprirà una nuova finestra, ma non appena l'utente fa clic su Salva, la nuova finestra viene chiusa.


2
Questa è la migliore risposta. In Internet Explorer, l'aggiunta di "target =" _ blank "" a un collegamento che deve essere scaricato interromperà la navigazione del browser (dove viene stampato "HTML1300: navigazione avvenuta") e quindi la pagina potrebbe rimanere in uno stato incoerente.
user64141

23

Inseriscilo nella sezione HTML head, impostando la urlvar all'URL del file da scaricare:

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

Quindi inseriscilo nel body, che avvierà automaticamente il download dopo 5 secondi:

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

(Da qui .)


2
non funziona, perché in IE6, se l'utente fa clic su "salva" il file viene salvato, ma il popup rimane aperto. Questo non è accettabile.
mkoryak

questo codice non funziona in safari puoi aiutarmi a risolverlo in safari per favore.
Renish Khunt

17

So che la domanda è stata posta 7 years and 9 months agoma molte soluzioni pubblicate non sembrano funzionare, ad esempio l'utilizzo di un <iframe>funziona solo con FireFoxe non funziona con Chrome.

Soluzione migliore:

La migliore soluzione di lavoro per aprire un pop-up di download di file JavaScriptè utilizzare un HTMLelemento di collegamento, senza la necessità di aggiungere l'elemento di collegamento adocument.body come indicato in altre risposte.

È possibile utilizzare la seguente funzione:

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

Nella mia applicazione, lo sto usando in questo modo:

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

Demo funzionante:

Nota:

  • Devi usare l' link.downloadattributo in modo che il browser non apra il file in una nuova scheda e attivi il popup di download.
  • Questo è stato testato con diversi tipi di file (docx, xlsx, png, pdf, ...).

Quale sarebbe il modo migliore per visualizzare una gif in caricamento fino al download del file?
Ctrl_Alt_Defeat il

1
@Ctrl_Alt_Defeat Bene in questo caso non sarà facile tenere traccia del processo di download, ma un trucco può essere quello di mostrare questa animazione gif al linkclic e nasconderla dopo un timeout, usando questo codice link.onclick = function() { document.body.innerText = "The file is being downloaded ..."; setTimeout(function() { document.body.innerText = ""; }, 2000); }:, puoi vederlo funzionare in questo violino , ma tieni presente che non è un modo consigliato per farlo, sarebbe meglio gestito se usassimo Ajax.
cнŝdk

1
non funziona in Firefox. come scaricare in Firefox?
Manoj Rana

@ManojRana Per firefox, puoi usare un iframevedere questa risposta .
cнŝdk

2
Questa soluzione funziona in Chrome, Safari e Firefox per me :)
ariebear

15

Ho cercato un buon modo per utilizzare javascript per avviare il download di un file, proprio come suggerisce questa domanda. Tuttavia queste risposte non sono state utili. Ho quindi eseguito alcuni test su xbrowser e ho scoperto che un iframe funziona meglio su tutti i browser moderni 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" è la mia classe per definire lo stile dei contenuti presenti ma non visualizzabili.

css:

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

uguale a .visuallyHidden in html5boilerplate

Lo preferisco al metodo window.open di javascript perché se il collegamento è interrotto il metodo iframe semplicemente non fa nulla invece di reindirizzare a una pagina vuota dicendo che il file non può essere aperto.

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

6

Utilizzo dell'API file URL oggetto Blob HTML5 :

/**
 * 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)


2
Penso che questo sia il modo migliore per farlo !!
Kushal MK

1
È anche una buona pratica chiamare URL.revokeObjectURL(url), quando il file non è più necessario per liberare la memoria
SleepWalker

5

La modifica della posizione della finestra potrebbe causare qualche problema soprattutto quando si dispone di una connessione persistente come websocket. Quindi ricorro sempre alla buona vecchia soluzione 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();
}

5

Se il collegamento è a un URL di file valido, funzionerà semplicemente assegnando window.location.href.

Tuttavia, a volte il collegamento non è valido ed è necessario un iFrame.

Esegui il normale event.preventDefault per impedire l'apertura della finestra e, se stai usando jQuery, funzionerà:

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

2

Dopo ore di tentativi, è nata la funzione :) Avevo uno scenario in cui dovevo visualizzare il caricatore in tempo mentre il file si preparava per il download:

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

0

Che ne dite di:

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

In questo modo funziona su tutti i browser (credo) e ti consente di inserire un messaggio del tipo: "Se il download non inizia entro cinque secondi, fai clic qui".

Se hai bisogno che sia con javascript .. beh ...

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

Saluti


0

Un iframe piccolo / nascosto può funzionare a questo scopo.

In questo modo non devi preoccuparti di chiudere il popup.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.