Comment déclencher un téléchargement de fichier en cliquant sur un bouton HTML ou JavaScript

434

C'est fou mais je ne sais pas comment faire, et à cause de la fréquence des mots, il est difficile de trouver ce dont j'ai besoin sur les moteurs de recherche. Je pense que cela devrait être facile à répondre.

Je veux un téléchargement de fichier simple, qui ferait la même chose que ceci:

<a href="file.doc">Download!</a>

Mais je veux utiliser un bouton HTML, par exemple l'un ou l'autre:

<input type="button" value="Download!">
<button>Download!</button>

De même, est-il possible de déclencher un simple téléchargement via JavaScript?

$("#fileRequest").click(function(){ /* code to download? */ });

Je ne cherche certainement pas un moyen de créer une ancre qui ressemble à un bouton, d'utiliser des scripts principaux ou de jouer avec les en-têtes de serveur ou les types MIME.

brentonstrine
la source
15
Merci à vous "comment déclencher un téléchargement de fichier en javascript" donnerait des réponses beaucoup plus rapides pour tout futur chercheur.
Danubian Sailor

Réponses:

278

Pour le bouton que vous pouvez faire

<form method="get" action="file.doc">
   <button type="submit">Download!</button>
</form>
Cfreak
la source
Vous pouvez enregistrer la balise de formulaire et simplement ajouter un onclick à la balise bouton.
Florian Leitgeb
12
ne fonctionne pas comme déclencheur, il suffit de rediriger vers l'URL en tant que balise «a».
fdrv
7
Cela fonctionne mieux: <a href="path_to_file" download="proposed_file_name"> Télécharger </a>
kscius
11
@kscius, même aujourd'hui, l'attribut de téléchargement n'est pas pris en charge dans IE 11 (il est désormais pris en charge dans Edge) et il n'est pas pris en charge dans Safari. En 2012, lorsque la réponse a été publiée à l'origine, elle n'était prise en charge par aucun navigateur majeur.
Cfreak
1
quelle est la différence entre une ancre avec un style de bouton et une forme avec un bouton?
Andrei Epure
444

Vous pouvez déclencher un téléchargement avec l' downloadattribut HTML5 .

<a href="path_to_file" download="proposed_file_name">Download</a>

Où:

  • path_to_fileest un chemin d'accès qui se résout en une URL de la même origine . Cela signifie que la page et le fichier doivent partager le même domaine, sous-domaine, protocole (HTTP vs HTTPS) et port (si spécifié). Les exceptions sont blob:et data:(qui fonctionnent toujours) et file:(qui ne fonctionnent jamais).
  • proposed_file_nameest le nom du fichier dans lequel enregistrer. S'il est vide, le navigateur utilise par défaut le nom du fichier.

Documentation: MDN , HTML Standard sur le téléchargement , HTML Standard surdownload , CanIUse

Joe Pigott
la source
37
Ne fonctionne pas avec Safari et certaines versions d'IE
Mohamed Hussain
4
L'utilisation d'une combinaison de downloadet target="_blank"semble suffisante pour couvrir la plupart des cas d'utilisation. Les navigateurs qui comprennent le downloadtraitent comme un téléchargement, sinon il est ouvert dans un nouvel onglet.
MK10
10
Comment cela peut-il être appliqué à un objet bouton au lieu d'une simple balise a ?
storm_m2138
8
En fait, cela ne fonctionne que pour les URL de la même origine que celles mentionnées dans les documents MDN. C'est une énorme limitation si nous cherchons à développer une solution générique
Akshat Gupta
6
La question demande explicitement d'utiliser un bouton au lieu d'un lien
Quentin
87

HTML:

<button type="submit" onclick="window.open('file.doc')">Download!</button>
sleepyup
la source
8
La meilleure solution et la plus propre. Mais vous n'avez pas besoin de Javascript supplémentaire ici. Une partie HTML avec le onclick suffit.
Florian Leitgeb
4
Et si je veux télécharger un fichier xml?
g07kore
2
Merci pour votre code. J'ai testé, il peut fonctionner sous IE, Chrome, Firefox.
muthukumar
6
Si vous avez un fichier acceptable par le navigateur comme un PDF, il s'ouvrira dans un nouvel onglet pour afficher la boîte de dialogue de téléchargement.
WindRider
1
window.open peut déclencher le blocage des fenêtres contextuelles dans un navigateur et n'est donc pas recommandé. Vous pouvez utiliser window.location = 'path', bien que cela irait à l'emplacement dans la même fenêtre de navigateur.
Elendurwen
68

Avec jQuery:

$("#fileRequest").click(function() {
    // // hope the server sets Content-Disposition: attachment!
    window.location = 'file.doc';
});
Matt Ball
la source
1
Parfait merci. Savez-vous par hasard si la plupart des serveurs définiront la disposition de contenu sur «pièce jointe» par défaut?
brentonstrine
5
Il n'y a pas de «plus». Cela dépend complètement. Ne comptez pas sur le réglage.
Matt Ball
3
Ce problème m'a rendu balistique, et c'était la seule option qui a fonctionné (et est prise en charge par IE). J'ajouterai pour tout n00bs comme moi que pour définir le Content-Disposition, tout ce que vous avez à faire est: <? Php header ('Content-Disposition: attachment; filename = "filename.here"'); ?>
user124384
3
Pas de requête. Période.
Adam Arold
1
Cela fonctionne si vous essayez de télécharger une image, cela ouvrirait l'image dans le navigateur
Dheeraj
34

Ancien thread mais il manque une solution js simple:

let a = document.createElement('a')
a.href = item.url
a.download = item.url.split('/').pop()
document.body.appendChild(a)
a.click()
document.body.removeChild(a)
Stefanos Chrs
la source
24
@NicholasKyriakides Type de me rappelle ce joyau: image.ibb.co/dtkUWJ/Selection_002.png
Stefanos Chrs
@BryanLarsen quelle version de FF?
Stefanos Chrs
1
@BryanLarsen Vous avez raison, Firefox ne permet pas cela sans ajouter d'abord l'élément au corps. Merci d'avoir mis à jour la réponse
Stefanos Chrs
1
Existe-t-il un moyen de déclencher la fonction javascript une fois le téléchargement terminé? J'essaie simplement d'afficher un message une fois le téléchargement démarré et de supprimer le message une fois le téléchargement terminé.
mohit bansal
1
@mohitbansal (un) heureusement non car c'est au niveau du navigateur
Stefanos Chrs
23

Vous pouvez le faire avec "truc" avec iframe invisible. Lorsque vous lui définissez "src", le navigateur réagit comme si vous cliquiez sur un lien avec le même "href". Contrairement à la solution avec formulaire, il vous permet d'incorporer une logique supplémentaire, par exemple l'activation du téléchargement après expiration, lorsque certaines conditions sont remplies, etc.

Il est également très silencieux, il n'y a pas de nouvelle fenêtre / onglet clignotant comme lors de l'utilisation window.open.

HTML:

<iframe id="invisible" style="display:none;"></iframe>

Javascript:

function download() {
    var iframe = document.getElementById('invisible');
    iframe.src = "file.doc";
}
Marin danubien
la source
C'est le cas, du moins si vous approuvez réellement l'iframe de document.body.
yxhuvud
1
Cela ne semble pas fonctionner dans Chrome en ce moment, même si cela fonctionnait auparavant. Je me demande si cela cesse de fonctionner par intermittence dans différentes versions de Chrome.
Dobes Vandermeer
Fonctionne dans Chrome à partir de la version 61.0.3163.100 (version officielle) (64 bits)
AndrewBenjamin
Ne fonctionne pas avec les images dans Firefox v57. Il rend juste l'image dans l'iframe.
Antony
15

Version d'amorçage

<a class="btn btn-danger" role="button" href="path_to_file"
   download="proposed_file_name">
  Download
</a>

Documenté dans la documentation de Bootstrap 4 et fonctionne également dans Bootstrap 3.

Support CFP
la source
9
La seule chose que cela a à voir avec Bootstrap, ce sont les noms de classe, c'est juste la puissance de HTML5.
Machado
3
La question demande explicitement comment faire cela avec un bouton au lieu d'un lien.
Quentin
2
si vous saviez quelque chose sur le bootstrap, vous verriez que C'EST un bouton.
John Lord
11

Je pense que c'est la solution que vous cherchiez

<button type="submit" onclick="window.location.href='file.doc'">Download!</button>

J'ai un cas où mon Javascript a généré un fichier CSV. Puisqu'il n'y a pas d'URL distante pour le télécharger, j'utilise l'implémentation suivante.

downloadCSV: function(data){
    var MIME_TYPE = "text/csv";

    var blob = new Blob([data], {type: MIME_TYPE});
    window.location.href = window.URL.createObjectURL(blob);
}
Delconis
la source
sur 404 -> changement de page en page d'erreur 404. même problème que celui indiqué sur les autres location.hrefsolutions.
BananaAcid
9

Qu'en est-il de:

<input type="button" value="Download Now!" onclick="window.location = 'file.doc';">
olli
la source
5
Cela ne fonctionne pas, si votre fichier, par exemple, est une image, car il serait juste ouvert dans le navigateur.
Juggernaut
Un autre problème se produit: si le fichier est manquant, il navigue sur toute la page vers une page 404
Hugheth
7

Vous pouvez masquer le lien de téléchargement et cliquer dessus.

<button onclick="document.getElementById('link').click()">Download!</button>
<a id="link" href="file.doc" download hidden></a>
Starwarswii
la source
Pour que cela fonctionne dans Firefox, la ressource doit être sur le même domaine que le document. La définition des en-têtes CORS n'aide pas .
Antony
2
Ne faites jamais ça
Wannes
@Wannes pourquoi pas?
Starwarswii
4

Si vous recherchez une solution JavaScript vanille (pas de jQuery) et sans utiliser l'attribut HTML5, vous pouvez essayer ceci.

const download = document.getElementById("fileRequest");

download.addEventListener('click', request);

function request() {
    window.location = 'document.docx';
}
.dwnld-cta {
    border-radius: 15px 15px;
    width: 100px;
    line-height: 22px
}
<h1>Download File</h1>
<button id="fileRequest" class="dwnld-cta">Download</button>

David Willhite
la source
1

C'est ce qui a finalement fonctionné pour moi puisque le fichier à télécharger a été déterminé lors du chargement de la page.

JS pour mettre à jour l'attribut d'action du formulaire:

function setFormAction() {
    document.getElementById("myDownloadButtonForm").action = //some code to get the filename;
}

Appel de JS pour mettre à jour l'attribut d'action du formulaire:

<body onLoad="setFormAction();">

Balise de formulaire avec le bouton d'envoi:

<form method="get" id="myDownloadButtonForm" action="">
    Click to open document:  
    <button type="submit">Open Document</button>
</form>

Les éléments suivants n'ont PAS fonctionné:

<form method="get" id="myDownloadButtonForm" action="javascript:someFunctionToReturnFileName();">
slayernoah
la source
probablement parce que si vous avez le fichier au moment du chargement, ne pouvez-vous pas simplement rendre l'action sur le serveur à l'aide d'un moteur de modèles? pourquoi le besoin de code js?
Andrei Epure
1

Si vous ne pouvez pas utiliser le formulaire, une autre approche avec downloadjs convient bien. Downloadjs utilise l'API de fichier blob et html 5 sous le capot:

{downloadjs (url, nom de fichier)}) />

* c'est la syntaxe jsx / react, mais peut être utilisée en html pur

Gleb Dolzikov
la source
Pour éviter les problèmes CORS pour les images d'autres domaines, mettez crossorigin = "anonymous" dans la balise img, comme ceci: <img src = "image.png" crossorigin = "anonymous" />
Jonathan Harris
0

N'importe où entre vos balises <body>et </body>, insérez un bouton en utilisant le code ci-dessous:

<button>
    <a href="file.doc" download>Click to Download!</a>
</button>

C'est sûr de fonctionner!

Ronaldo
la source
1
Pour Chrome, c'est une excellente solution
Hayk Aramyan
1
Ne fonctionne pas non plus dans Safari: écoles W3
Alex
2
Ne pas fonctionner dans les navigateurs MS est un problème assez important et Chrome ne sera pas toujours la réponse.
SudoKid
Vous ne pouvez pas mettre un lien à l'intérieur d'un bouton en HTML
Quentin
0

Une autre façon de faire si vous avez une URL complexe telle que l' file.doc?foo=bar&jon=doeajout d'un champ caché à l'intérieur du formulaire

<form method="get" action="file.doc">
  <input type="hidden" name="foo" value="bar" />
  <input type="hidden" name="john" value="doe" />
  <button type="submit">Download Now</button>
</form>

inspiré de la réponse @Cfreak qui n'est pas complète

Bellash
la source
0

vous pouvez ajouter une balise sans texte mais avec un lien. et lorsque vous cliquez sur le bouton comme dans le code, exécutez simplement la fonction $ ("yourlinkclass"). click ().

ThisisFish
la source
-1

attribut de téléchargement

 <a class="btn btn-success btn-sm" href="/file_path/file.type" download>
     <span>download </span>&nbsp;<i class="fa fa-download"></i>
 </a>
Rohallah Hatami
la source
2
J'aime votre réponse
George C.
2
La question demande explicitement comment faire cela avec un bouton au lieu d'un lien.
Quentin
-6

Si vous utilisez la <a>balise, n'oubliez pas d'utiliser l'URL entière qui mène au fichier - c'est-à-dire:

<a href="http://www.example.com/folder1/file.doc">Download</a>
marque
la source
Je ne pense pas que ce soit le problème ici. De plus, le chemin "absolu" n'est pas nécessaire si le lien est dans le même chemin que le fichier.
Rocket Hazmat
@Rocket - vous avez, bien sûr, raison sur le chemin absolu, cependant, c'est la meilleure façon de vous assurer de bien faire les choses. Je laisserai au PO le soin de décider si cela a été utile -
Mark
La question demande explicitement comment faire cela avec un bouton au lieu d'un lien.
Quentin
l'attribut de téléchargement est manquant dans cette solution. Même après avoir ajouté des attributs de téléchargement, cela ne fonctionnera pas pour les domaines croisés.
s sharif
-6

Pour moi, ajouter un bouton au lieu d'un texte d'ancrage fonctionne très bien.

<a href="file.doc"><button>Download!</button></a>

Ce n'est peut-être pas correct selon la plupart des règles, mais ça a l'air plutôt bien.

Brana
la source
5
Cela ne fonctionne que parce que votre navigateur ne prend pas en charge les fichiers .doc.
Design par Adrian
Votre code HTML n'est pas valide. <a>les éléments ne peuvent pas contenir d' <button>éléments.
Quentin
était-ce toujours ainsi? Cette réponse datait de deux ans lorsque vous avez commenté cela.
John Lord