(HTML) Téléchargez un fichier PDF au lieu de l'ouvrir dans le navigateur lorsque vous cliquez dessus

115

Je me demandais comment rendre un lien de fichier PDF téléchargeable au lieu de les ouvrir dans le navigateur? Comment cela se fait-il en html? (Je suppose que c'est fait via javascript ou quelque chose).

404Erreur
la source
3
C'est à ma connaissance un comportement non scriptable. La plupart des navigateurs auront leurs propres paramètres pour savoir quoi faire avec des types de fichiers spécifiques lors du téléchargement.
Bart
1
À partir de HTML5, l'OP devrait mettre à jour la bonne réponse à la réponse de Sarim.
Omar Tariq
duplication possible de Force pour ouvrir le popup "Enregistrer sous ..." ouvrir au lien texte cliquez pour pdf en HTML
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
Cette question a également reçu une réponse ici: stackoverflow.com/a/30714824/847235
intrepidis

Réponses:

38

Vous ne pouvez pas faire cela avec HTML. C'est une solution basée sur un serveur. Vous devez diffuser le fichier pour que le navigateur déclenche la boîte de dialogue d'enregistrement.

Je conseillerais de ne pas faire cela. La façon dont un utilisateur interagit avec un PDF doit être laissée à l'utilisateur.

MISE À JOUR (2014):

Donc ... cette réponse reçoit encore beaucoup de votes négatifs. Je suppose qu'une partie de cela est que cela a été répondu il y a 4 ans et comme le souligne Sarim, il y a maintenant l' attribut HTML 5download qui peut gérer cela.

Je suis d'accord, et je pense que la réponse de Sarim est bonne (elle devrait probablement être la réponse choisie si le PO revient un jour). Cependant, cette réponse reste le moyen fiable de la gérer (comme le souligne la réponse de Yiğit Yener et - curieusement - les gens sont d'accord). Bien que l'attribut de téléchargement soit pris en charge, il est toujours irrégulier:

http://caniuse.com/#feat=download

DA.
la source
18
Je sais que c'est un an - mais je ne suis pas d'accord. Il existe des circonstances dans lesquelles forcer ce comportement est très important pour le flux d'application. La vraie réponse est de définir la disposition du contenu dans l'en-tête pour qu'elle soit "pièce jointe" au lieu de "en ligne".
user158017
9
Je reconnais que dans d'autres circonstances, il est préférable de laisser le contrôle à l'utilisateur. Cependant, je suis venu sur ce fil à la recherche d'une réponse, et la case "réponse" cochée n'était pas une réponse - c'était "tu ne devrais pas faire ça". Pour moi, ce n'est pas une réponse à la question. réponse spécifique et également conseiller.
user158017
1
Parfois, la question est fausse. ;) Quoi qu'il en soit, concernant votre problème, c'est tout un problème UX. Il est parfois nécessaire de forcer le Web à se comporter de manière spécifique, mais il existe souvent de meilleures solutions d'un point de vue UX. De plus, ma réponse est correcte. Vous ne pouvez pas faire ce que vous voulez faire avec HTML (c'est ce que la question posait). C'est comme une solution côté serveur.
DA.
1
C'est l'une de mes réponses les plus étranges jamais publiées. Les gens trouvent toujours leur chemin ici pour voter contre. Ce qui est bien! Mais il serait intéressant de savoir pourquoi.
DA.
3
À propos de ce vote à la baisse, cela peut être la chute de la civilisation à quel point il est facile de tomber sur un texte involontairement arrogant . Cette réponse me semble longue sur l'opinion condescendante et courte sur les réponses. Au lieu du paragraphe 1, ajoutez simplement la httpbalise à la question. Au lieu du paragraphe 2: "Vous voudrez peut-être reconsidérer si empêcher la visualisation immédiate du PDF est dans le meilleur intérêt de tous les utilisateurs. Cela dit ..." Alors supposez que le PO et les futurs lecteurs sont des adultes et passez à une réponse concrète telle que celle de Yener .
Bob Stein
133

Avec html5, c'est désormais possible. Définissez un attr "téléchargement" dans l'élément.

<a href="http://link/to/file" download="FileName">Download it!</a>

Source: http://updates.html5rocks.com/2011/08/Downloading-resources-in-HTML5-a-download

Sarim
la source
Vous feriez mieux d'utiliser cette solution si elle est prise en charge. Voici un moyen de vérifier si c'estif ("download" in document.createElement("a")){ ... }
pmrotule
J'ai ajouté une autre réponse ci-dessous (mauvais hack cependant), bien que ce soit toujours le moyen préféré, peut-être que le moyen de piratage pourrait être proposé pour les navigateurs non pris en charge.
Sarim
Existe-t-il un moyen de spécifier le texte du pdf au lieu de mentionner le chemin du fichier? J'ai besoin de créer un pdf à partir d'un html div mais je ne souhaite pas ouvrir une autre fenêtre, le téléchargement devrait être simple comme dans cette réponse ..
T.Adak
1
En ce moment d'août 2019, la prise en charge du navigateur semble être améliorée pour cette fonctionnalité, voir: w3schools.com/tags/att_a_download.asp
Daniel Resch
2
Notez que l'attribut de téléchargement n'est pris en charge que pour les demandes de même origine.
Quentin
82

Cela n'est possible qu'en définissant un en-tête de réponse http par le code côté serveur. À savoir;

Content-Disposition: attachment; filename=fname.ext
Yiğit Yener
la source
2
c'est la réponse parfaite - il suffit de trouver le moyen de le faire dans la langue appropriée côté serveur.
user158017
Exemple Apache . Exemple de flacon .
Bob Stein
Malheureusement, iOS affichera toujours un aperçu et ne téléchargera pas les fichiers PDF même si la disposition du contenu est «pièce jointe».
Jorn van de Beek
14

Vous devez modifier les en-têtes http envoyés. En fonction de votre serveur, vous pouvez modifier votre .htaccess comme suit:

<FilesMatch "\.(?i:pdf)$">
  ForceType application/octet-stream
  Header set Content-Disposition attachment
</FilesMatch>
gars php
la source
Il n'est pas nécessaire de mentir sur le type de contenu. La définition de la disposition du contenu est suffisante.
Quentin
9

vous devrez utiliser un script PHP (ou un autre langage côté serveur pour cela)

<?php
// We'll be outputting a PDF
header('Content-type: application/pdf');

// It will be called downloaded.pdf
header('Content-Disposition: attachment; filename="downloaded.pdf"');

// The PDF source is in original.pdf
readfile('original.pdf');
?>

et utilisez httacces pour rediriger (réécrire) vers le fichier PHP au lieu du pdf

barbe
la source
Hmm, cela fonctionne très bien lorsque j'ouvre directement le fichier php. Mais lorsque j'essaie d'utiliser la redirection, comme ici: Rediriger 301 /_PDFs/Catalogue.pdf http://www.example.com/_PDFs/___download_the_catalogue_instead_opening.phpet essayer d'ouvrir le fichier pdf, il ouvre toujours l'original dans le navigateur, téléchargeant à la place la version renommée ...
ellockie
UPDATE: Cela fonctionne quand il n'y a pas de fichier qui est directement appelé (comme "Catalogue.pdf" dans mon exemple). Ensuite, la redirection fonctionne parfaitement. Merci!
ellockie le
8

Vous pouvez utiliser

Response.AddHeader("Content-disposition", "attachment; filename=" + Name);

Regardez cet exemple:

http://www.codeproject.com/KB/aspnet/textfile.aspx

Cela vaut pour ASP.NET. Je suis sûr que vous pouvez trouver des solutions similaires dans toutes les autres langues côté serveur. Cependant, il n'y a pas de solution javascript à ma connaissance.

mihsathe
la source
c'est la réponse (ainsi que celle associée pour PHP). le fait est que l'en-tête de la réponse http doit être édité.
user158017
5

Sans attribut html5, on peut y parvenir en utilisant php:

Créez un fichier php nommé download.php avec ce code:

<?php
ob_start();
$file = "yourPDF.pdf"

if (file_exists($file)) 
{
    header('Content-Description: File Transfer');
    header('Content-Type: application/octet-stream');
    header('Content-Disposition: attachment; filename='.basename($file));
    header('Content-Transfer-Encoding: binary');
    header('Expires: 0');
    header('Cache-Control: must-revalidate');
    header('Pragma: public');
    header('Content-Length: ' . filesize($file));
    ob_clean();
    flush();
    readfile($file);
    exit();
}

Maintenant, si vous souhaitez démarrer automatiquement le téléchargement de pdf, écrivez ce javascript:

<script>window.location = "download.php";</script>

Si vous voulez que cela fonctionne sur un lien, utilisez ceci ...

<a href='javascript:window.location = "download.php"'>
    Download it!
</a>
hlozancique
la source
4
Juste un avertissement que vous devez faire attention lorsque vous allez faire cela avec des paramètres d'URL. Par exemple $file = $_GET['$file'];. Parce qu'on pourrait alors aussi appeler download.php?file=../../../wp-config.phpou toute autre ressource donnée. Il est très important de vérifier les extensions, les types mime et les chemins autorisés à télécharger (et supprimer des éléments comme "../")!
Giel Berkers
est-ce moi ou faire <a href='javascript...'> est exactement la même chose que mettre directement le lien dans<a href='download.php'> ?
allan.simon
5

Lorsque vous souhaitez télécharger directement une image ou un fichier pdf à partir du navigateur au lieu de l'ouvrir dans un nouvel onglet, vous devez définir la valeur en javascript pour télécharger l'attribut de création de lien dynamique

    var path= "your file path will be here"; 
    var save = document.createElement('a');  
    save.href = filePath; 
    save.download = "Your file name here"; 
    save.target = '_blank'; 
    var event = document.createEvent('Event');
    event.initEvent('click', true, true); 
    save.dispatchEvent(event);
   (window.URL || window.webkitURL).revokeObjectURL(save.href);

Pour la nouvelle mise à jour de Chrome, un événement temporel ne fonctionne pas. pour que le code suivant soit utilisé

  var path= "your file path will be here"; 
    var save = document.createElement('a');  
    save.href = filePath; 
    save.download = "Your file name here"; 
    save.target = '_blank'; 
    document.body.appendChild(save);
    save.click();
    document.body.removeChild(save);

L'ajout d'un enfant et la suppression d'un enfant sont utiles pour Firefox, navigateur Internet Explorer uniquement. Sur Chrome, cela fonctionnera sans ajouter ni supprimer l'enfant

Prasad Joshi
la source
2

La solution qui fonctionnait le mieux pour moi était celle rédigée par Nick sur son blog

L'idée de base de sa solution est d'utiliser le mod d'en-tête des serveurs Apache et de modifier le .htaccess pour inclure une directive FileMatch qui force tous les fichiers * .pdf à agir comme un flux au lieu d'une pièce jointe. Bien que cela n'implique pas réellement d'éditer du HTML (selon la question originale), cela ne nécessite aucune programmation en soi.

La première raison pour laquelle j'ai préféré l'approche de Nick est qu'elle m'a permis de le définir par dossier afin que les fichiers PDF dans un dossier puissent toujours être ouverts dans le navigateur tout en permettant à d'autres (ceux que nous aimerions que les utilisateurs modifient puis retéléchargent) d'être forcé en tant que téléchargements.

Je voudrais également ajouter qu'il existe une option avec les PDF pour publier / soumettre des formulaires à remplir via une API à vos serveurs, mais cela prend du temps à mettre en œuvre.

La deuxième raison était que le temps est une considération. L'écriture d'un gestionnaire de fichiers PHP pour forcer la disposition du contenu dans l'en-tête () prendra également moins de temps qu'une API, mais toujours plus longue que l'approche de Nick.

Si vous savez comment activer un mod Apache et modifier le .htaccss, vous pouvez l'obtenir en 10 minutes environ. Il nécessite un hébergement Linux (pas Windows). Cette approche peut ne pas être appropriée pour toutes les utilisations car la configuration nécessite un accès serveur de haut niveau. En tant que tel, si vous avez dit accès, c'est probablement parce que vous savez déjà comment faire ces deux choses. Sinon, consultez le blog de Nick pour plus d'instructions.

Strixy
la source
2

Comme la méthode html5 (ma réponse précédente) n'est pas disponible dans tous les navigateurs, voici une autre façon légèrement hack.

Cette solution nécessite que vous diffusiez le fichier prévu à partir du même domaine, OU que vous disposiez de l'autorisation CORS.

  1. Téléchargez d'abord le contenu du fichier via XMLHttpRequest (Ajax).
  2. Créez ensuite un URI de données en encodant en base64 le contenu du fichier et définissez le type de média sur application/octet-stream. Le résultat devrait ressembler à

data:application/octet-stream;base64,SGVsbG8sIFdvcmxkIQ%3D%3D

Maintenant prêt location.href = data. Cela amènera le navigateur à télécharger le fichier. Malheureusement, vous ne pouvez pas définir le nom ou l'extension du fichier de cette façon. Jouer avec le type de média pourrait donner quelque chose.

Voir les détails: https://developer.mozilla.org/en-US/docs/Web/HTTP/data_URIs

Sarim
la source
1

J'avais besoin de le faire pour les fichiers créés avec des noms dynamiques dans un dossier particulier et servis par IIS.

Cela a fonctionné pour moi:

  • Dans IIS, accédez à ce dossier et double-cliquez sur En-têtes de réponse HTTP.
  • Ajoutez un nouvel en-tête avec les informations suivantes:

    Name: content-disposition Value: attachment

(à partir de: http://forums.iis.net/t/1175103.aspx?add+CustomHeaders+only+for+certain+file+types+ )

EricL
la source
1

Si vous utilisez HTML5 (et je suppose que maintenant, tout le monde l'utilise), il y a un attribut appelé download.

ex. <a href="somepathto.pdf" download="filename">

ici filenameest facultatif, mais s'il est fourni, il prendra ce nom pour le fichier téléchargé.

Akshay
la source
Malheureusement, je dois admettre que je suis trop stupide pour comprendre cette balise. Je mets ceci: <a href="download/Curriculum_it.pdf.zip">Download curriculum</a>ou cela: <a href="download/Curriculum_it.pdf.zip" download="Curriculum_it">Download curriculum</a>et je ne vois absolument aucune différence dans la façon dont cela fonctionne. Les deux téléchargeant mon .zip. Et dans le second, l'utilisation de l'option filename semble ne rien faire du tout.
Garavani
0

Le comportement doit dépendre de la configuration du navigateur pour gérer divers types MIME. Dans ce cas, le type MIME est application / pdf. Si vous souhaitez forcer le navigateur à télécharger le fichier, vous pouvez essayer de forcer un type MIME différent sur les fichiers PDF. Je déconseille cela, car les utilisateurs doivent choisir ce qui se passera lorsqu'ils ouvriront un fichier PDF.

Aleksi Yrttiaho
la source
0

Vous pouvez utiliser download.js ( https://github.com/rndme/download et http://danml.com/download.html ). Si le fichier est dans une URL externe, vous devez faire une requête Ajax, mais si ce n'est pas le cas, vous pouvez utiliser la fonction:

download(Path, name, mime)

Lisez leur documentation pour plus de détails dans le GitHub.

Vishnu S.
la source
C'est la meilleure solution javascript pour les téléchargements dans un autre domaine.
Edhowler le
-1

Enfin j'ai trouvé ...... créer une balise d'ancrage dynamique et cliquer dessus

<script> 
   $('#myclick').click(function(){
       $('body').append('<a id="link" href="mypdf.pdf" 
        download="Payment.pdf">&nbsp;</a>');
       $('#link')[0].click();
   });
</script>

«Payment.pdf» est uniquement pour le nom personnalisé.

Pushpender Singh
la source
Il n'est pas nécessaire de générer le lien dynamiquement.
Quentin
Notez que l'attribut de téléchargement n'est pris en charge que pour les demandes de même origine.
Quentin
Cela semble être la même réponse que celle-ci de trois ans plus tôt.
Quentin