Le moyen le plus simple d'ouvrir une fenêtre de téléchargement sans quitter la page


119

Quel est le meilleur moyen pour plusieurs navigateurs d'ouvrir une boîte de dialogue de téléchargement (supposons que nous puissions définir content-disposion: attachment dans les en-têtes) sans quitter la page actuelle ou ouvrir des fenêtres contextuelles, ce qui ne fonctionne pas bien dans Internet Explorer (IE ) 6.

Réponses:


106

7 ans se sont écoulés et je ne sais pas si cela fonctionne pour IE6 ou non, mais cela invite OpenFileDialog dans FF et 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);

Tout d'abord merci pour cette solution, mais j'ai trouvé un bug si removeChild (a) le zip décompressera l'erreur avec zip est cassé, alors supprimez ce code résolvez-le
Roy

2
@Manoj Rana - J'ai vérifié sur FF 58.0.2 (64 bits) qu'il fonctionne. Cela ne fonctionnera sur aucun FF si vous supprimez 2 lignes document.body.appendChild (a); document.body.removeChild (a);
0x000f

1
Pour que cela fonctionne sur Edge 16, l'en-tête, d'où provient le fichier, doit contenir Content-Type: application/octet-streamet Content-Disposition: attachment.
Simon


2
@ user1933131 chrome supprime uniquement pour l'origine
croisée

202

Ce javascript est bien qu'il n'ouvre pas une nouvelle fenêtre ou un nouvel onglet.

window.location.assign(url);

18
C'est la même chose que window.location = url; «Chaque fois qu'une nouvelle valeur est attribuée à l'objet de localisation, un document sera chargé en utilisant l'URL comme si window.location.assign () avait été appelée avec l'URL modifiée» - developer.mozilla.org/en-US/docs/ Web / API / window.location
Rob Juurlink

13
Cela provoque la déconnexion de la connexion WebSocket.
igorpavlov

4
J'ai utilisé la même solution mais cela ouvre le fichier dans le même onglet au lieu d'ouvrir une boîte de dialogue de téléchargement.
Techno Cracker

2
c'est la même chose pour window.open (url, '_self') si l'url est pour la page de téléchargement alors.
expert veut être le

5
Lors de l'utilisation d'IE11, j'ai constaté que cela provoquait l'arrêt de JS. Donc, pour IE 11, j'ai utilisé window.open (url, '_blank') qui a ouvert un autre onglet, mais cet onglet s'est fermé lorsqu'il a fonctionné, le fichier était un téléchargement. Cela a permis au JS de fonctionner.
Luke

23

J'ajoute toujours un target = "_ blank" au lien de téléchargement. Cela ouvrira une nouvelle fenêtre, mais dès que l'utilisateur cliquera sur Enregistrer, la nouvelle fenêtre se fermera.


2
C'est la meilleure réponse. Dans Internet Explorer, l'ajout de 'target = "_ blank"' à un lien qui doit être téléchargé empêchera le navigateur de s'éloigner (où "HTML1300: la navigation s'est produite" est imprimé) et peut donc laisser la page dans un état incohérent.
user64141

23

Mettez ceci dans la section HTML head, en définissant le urlvar sur l'URL du fichier à télécharger:

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

Ensuite, mettez-le dans le corps, ce qui démarrera le téléchargement automatiquement après 5 secondes:

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

(À partir d' ici .)


2
cela ne fonctionne pas, car dans IE6, si l'utilisateur clique sur "enregistrer", le fichier est enregistré, mais la fenêtre contextuelle reste ouverte. Ceci est inacceptable.
mkoryak

ce code ne fonctionne pas en safari, pouvez-vous m'aider à le résoudre en safari s'il vous plaît.
Renish Khunt

17

Je sais que la question a été posée, 7 years and 9 months agomais de nombreuses solutions publiées ne semblent pas fonctionner, par exemple l'utilisation d'un <iframe>fonctionne uniquement avec FireFoxet ne fonctionne pas avec Chrome.

Meilleure solution:

La meilleure solution de travail pour ouvrir une fenêtre contextuelle de téléchargement de fichier dans JavaScriptest d'utiliser un HTMLélément de lien, sans avoir besoin d'ajouter l'élément de lien audocument.body comme indiqué dans d'autres réponses.

Vous pouvez utiliser la fonction suivante:

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

Dans mon application, je l'utilise de cette façon:

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

Démo de travail:

Remarque:

  • Vous devez utiliser l' link.downloadattribut pour que le navigateur n'ouvre pas le fichier dans un nouvel onglet et déclenche la fenêtre de téléchargement.
  • Cela a été testé avec plusieurs types de fichiers (docx, xlsx, png, pdf, ...).

Quelle serait la meilleure façon d'afficher un gif de chargement jusqu'à ce que le fichier soit téléchargé?
Ctrl_Alt_Defeat

1
@Ctrl_Alt_Defeat Eh bien dans ce cas, il ne sera pas facile de suivre le processus de téléchargement, mais une astuce peut être de montrer cette animation gif sur le linkclic et de la masquer après un délai d'attente, en utilisant ce code :, link.onclick = function() { document.body.innerText = "The file is being downloaded ..."; setTimeout(function() { document.body.innerText = ""; }, 2000); }vous pouvez le voir fonctionner dans ce violon , mais gardez à l'esprit que ce n'est pas une façon recommandée de le faire, ce serait mieux géré si nous utilisions Ajax.
cнŝdk

1
cela ne fonctionne pas dans Firefox. comment télécharger dans firefox?
Manoj Rana

@ManojRana Pour Firefox, vous pouvez utiliser et iframevoir cette réponse .
cнŝdk

2
Cette solution fonctionne dans Chrome, Safari et Firefox pour moi :)
ariebear

15

J'ai cherché un bon moyen d'utiliser javascript pour lancer le téléchargement d'un fichier, comme le suggère cette question. Cependant, ces réponses n'ont pas été utiles. J'ai ensuite fait des tests sur xbrowser et j'ai trouvé qu'une iframe fonctionne mieux sur tous les navigateurs modernes 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" est ma classe pour styliser le contenu qui est présent mais non visible.

css:

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

identique à .visuallyHidden dans html5boilerplate

Je préfère cela à la méthode javascript window.open car si le lien est rompu, la méthode iframe ne fait tout simplement rien, contrairement à la redirection vers une page vierge indiquant que le fichier ne peut pas être ouvert.

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

Utilisation de l' 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)


2
Je pense que c'est la meilleure façon de le faire !!
Kushal MK

1
Il est également URL.revokeObjectURL(url)
recommandé

5

La modification de l'emplacement de la fenêtre peut entraîner des problèmes, en particulier lorsque vous avez une connexion persistante telle que websocket. J'ai donc toujours recours à la bonne vieille solution 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

Si le lien est vers une URL de fichier valide, attribuer simplement window.location.href fonctionnera.

Cependant, parfois, le lien n'est pas valide et un iFrame est requis.

Faites votre event.preventDefault normal pour empêcher la fenêtre de s'ouvrir, et si vous utilisez jQuery, cela fonctionnera:

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

2

Après des heures d'essais, la fonction est née :) J'ai eu un scénario où je devais afficher le chargeur à temps pendant que le fichier se prépare pour le téléchargement:

Travailler dans Chrome, Safari et 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

Que diriez-vous:

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

Cette méthode fonctionne sur tous les navigateurs (je pense) et vous permet de mettre un message comme: "Si le téléchargement ne démarre pas dans cinq secondes, cliquez ici."

Si vous en avez besoin avec javascript ... eh bien ...

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

Cordialement


0

Une petite iframe cachée peut fonctionner à cet effet.

De cette façon, vous n'avez pas à vous soucier de fermer la fenêtre contextuelle.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.