Télécharger un fichier en utilisant Javascript/jQuery

J'ai une exigence très similaire spécifiée [ici][1].

J'ai besoin que le navigateur de l'utilisateur lance un téléchargement manuellement lorsque $('a#someID&#39 ;).click();.

Mais je ne peux pas utiliser la méthode window.href, car elle remplace le contenu de la page actuelle par le fichier que vous essayez de télécharger.

Je veux plutôt ouvrir le téléchargement dans une nouvelle fenêtre/un nouvel onglet. Comment cela est-il possible ?

[1] : https://stackoverflow.com/questions/1296085/download-file-using-jquery

Solution

Utilisez un <iframe> invisible :


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

Pour forcer le navigateur à télécharger un fichier qu'il serait autrement capable de rendre (comme des fichiers HTML ou texte), il faut que le serveur définisse le [Type MIME][1] du fichier à une valeur absurde, comme application/x-please-download-me ou alternativement application/octet-stream, qui est utilisé pour des données binaires arbitraires.

Si vous voulez seulement l'ouvrir dans un nouvel onglet, la seule façon de le faire est que l'utilisateur clique sur un lien dont l'attribut target est défini sur _blank.

En jQuery:

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

Chaque fois que l'utilisateur clique sur ce lien, il télécharge le fichier dans un nouvel onglet/fenêtre.

[1] : http://en.wikipedia.org/wiki/Internet_media_type

Commentaires (21)

Mise à jour des navigateurs modernes de 2019

C'est l'approche que je recommande maintenant, avec quelques réserves :

  • Un navigateur relativement moderne est nécessaire
  • S'il est prévu que le fichier soit très grand, vous devriez probablement faire quelque chose de similaire à l'approche originale (iframe et cookie) parce que certaines des opérations ci-dessous pourraient consommer de la mémoire système au moins aussi grande que le fichier téléchargé et/ou d'autres effets secondaires intéressants sur le 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!'));

Approche originale de 2012 basée sur jQuery/iframe/cookie.

J'ai créé le [plugin jQuery File Download][1] ([Demo][2]) ([GitHub][3]) qui pourrait également vous aider dans votre situation. Il fonctionne de manière assez similaire avec un iframe, mais possède quelques fonctionnalités intéressantes que j'ai trouvées très pratiques :

  • Très facile à configurer avec de beaux visuels (jQuery UI Dialog, mais pas nécessaire), tout est testé aussi

  • L'utilisateur ne quitte jamais la page à partir de laquelle il a lancé le téléchargement d'un fichier. Cette fonctionnalité devient cruciale pour les applications web modernes.

  • Les fonctions successCallback et failCallback vous permettent d'être explicite sur ce que l'utilisateur voit dans chaque situation.

  • En conjonction avec jQuery UI, un développeur peut facilement afficher une modale indiquant à l'utilisateur qu'un téléchargement de fichier est en cours, dissoudre la modale après le début du téléchargement ou même informer l'utilisateur de manière conviviale qu'une erreur s'est produite. Voir la [Démo][2] pour un exemple de ceci. J'espère que cela aidera quelqu'un !

Voici une démonstration d'un cas d'utilisation simple utilisant le plugin [source][4] avec des promesses. La [page de démonstration][2] contient également de nombreux autres exemples d'amélioration de l'interface utilisateur.

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

[1] : http://johnculviner.com/post/2012/03/22/Ajax-like-feature-rich-file-downloads-with-jQuery-File-Download.aspx [2] : http://jqueryfiledownload.apphb.com/ [3] : https://github.com/johnculviner/jquery.fileDownload [4] : http://github.com/johnculviner/jquery.fileDownload/blob/master/src/Scripts/jquery.fileDownload.js

Commentaires (10)

Si vous utilisez déjà jQuery, vous pouvez en profiter pour produire un extrait plus petit. Une version jQuery de la réponse d'Andrew :

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