148 votes

Comment rendre un fichier PDF téléchargeable dans un lien HTML ?

Je donne le lien d'un fichier pdf sur ma page web pour le téléchargement, comme ci-dessous

<a href="myfile.pdf">Download Brochure</a>

Le problème est que lorsque l'utilisateur clique sur ce lien alors

  • Si l'utilisateur a installé Adobe Acrobat, il ouvre le fichier dans la même fenêtre du navigateur dans Adobe Reader.
  • Si Adobe Acrobat n'est pas installé, une fenêtre contextuelle s'affiche pour permettre à l'utilisateur de télécharger le fichier.

Mais je veux que l'utilisateur soit toujours invité à télécharger, que "Adobe acrobat" soit installé ou non.

Veuillez me dire comment je peux faire cela ?

259voto

T_D Points 683

C'est un problème courant, mais peu de gens savent qu'il existe une solution simple en HTML 5 :

<a href="./directory/yourfile.pdf" download="newfilename">Download the pdf</a>

newfilename est le nom de fichier suggéré à l'utilisateur pour enregistrer le fichier. Si vous le laissez vide, le nom de fichier par défaut sera celui du serveur, comme ceci :

<a href="./directory/yourfile.pdf" download>Download the pdf</a>

Compatibilité : Je l'ai testé sur Firefox 21 et Iron, les deux fonctionnent bien. Il se peut que cela ne fonctionne pas sur les navigateurs incompatibles avec HTML5 ou obsolètes. Le seul navigateur que j'ai testé qui n'a pas forcé le téléchargement est IE...

9 votes

Il s'agit d'une solution simple, mais qui n'est malheureusement pas très bien supportée, notamment par IE. caniuse.com/#feat=download

2 votes

Oui, je sais. C'est pourquoi j'ai ajouté une note sur la compatibilité. Et selon votre source, IE et Safari ne supportent pas cette approche, ou du moins pas encore :) Quoi qu'il en soit, si vous voulez que tous les navigateurs forcent le téléchargement, je vous suggère de vérifier certaines des autres réponses à la place...

3 votes

Fonctionne comme un charme avec la version 39.0.2171.65 (64-bit) de chrome !

121voto

TravisO Points 6257

Au lieu de créer un lien vers le fichier .PDF, faites plutôt quelque chose comme

<a href="pdf_server.php?file=pdffilename">Download my eBook</a>

qui produit un en-tête personnalisé, ouvre le PDF (sécurité binaire) et imprime les données sur le navigateur de l'utilisateur, qui peut ensuite choisir d'enregistrer le PDF malgré les paramètres de son navigateur. Le fichier pdf_server.php devrait ressembler à ceci :

header("Content-Type: application/octet-stream");

$file = $_GET["file"] .".pdf";
header("Content-Disposition: attachment; filename=" . urlencode($file));   
header("Content-Type: application/octet-stream");
header("Content-Type: application/download");
header("Content-Description: File Transfer");            
header("Content-Length: " . filesize($file));
flush(); // this doesn't really matter.
$fp = fopen($file, "r");
while (!feof($fp))
{
    echo fread($fp, 65536);
    flush(); // this is essential for large downloads
} 
fclose($fp); 

PS : et bien sûr, effectuez quelques contrôles de bon sens sur la variable "file" pour empêcher les gens de voler vos fichiers, par exemple, n'acceptez pas les extensions de fichiers, ajoutez .pdf à la valeur.

0 votes

Est-ce vraiment important si j'utilise le code suivant : $file = $_GET["file"] .".pdf" ; AS $file = $_REQUEST["file"] .".pdf" ;

2 votes

Je suis confronté à un autre problème, mon fichier est situé à /products/brochure/myfile.pdf Je donne la variable $file comme $file_path = $_SERVER['DOCUMENT_ROOT'].'/products/brochure/' . $file ; mais il télécharge le fichier comme "%2Fvar%2Fwww%2Fweb15%2Fweb%2Fproducts%2Fbrochure%2myfile.pdf".

0 votes

Ce que je peux faire pour qu'il soit téléchargé avec le nom "monfichier.pdf" seulement. J'ai modifié l'en-tête ("Content-Disposition : attachment ; filename=" . urlencode('myfile.pdf')) ; également, mais cela ne fonctionne toujours pas.

50voto

Alex V Points 8406

Ne pas faire de boucle à travers chaque ligne du fichier. Utilisez fichier de lecture à la place, c'est plus rapide. Ceci est hors du site php : http://php.net/manual/en/function.readfile.php

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

Assurez-vous d'assainir votre variable get car quelqu'un pourrait télécharger des fichiers php...

5 votes

Le site fichier de lecture est en effet plus rapide. Je recommande personnellement d'utiliser cette réponse au lieu de la réponse acceptée

24voto

Rob W Points 125904

Plutôt que d'utiliser un script PHP, pour lire et vider le fichier, il est plus simple de réécrire l'en-tête en utilisant .htaccess . Cela permettra de conserver une "belle" URL ( myfile.pdf au lieu de download.php?myfile ).

<FilesMatch "\.pdf$">
ForceType applicaton/octet-stream
Header set Content-Disposition attachment
</FilesMatch>

0 votes

Est-ce que cela ne rendrait pas le téléchargement de TOUS vos PDF obligatoire ?

1 votes

@TecBrat Oui, mais c'est ce que le PO a demandé. Si vous voulez vous limiter à quelques PDF seulement, modifiez l'option ^\.pdf$ expression régulière.

2 votes

@TecBrat ou placez le fichier .htaccess uniquement dans le sous-dossier où ce comportement est nécessaire.

15voto

Alex W Points 11502

J'ai trouvé un moyen de le faire avec du bon vieux HTML et JavaScript/jQuery qui se dégrade gracieusement. Testé dans IE7-10, Safari, Chrome, et FF :

HTML pour le lien de téléchargement :

<p>Thanks for downloading! If your download doesn't start shortly, 
<a id="downloadLink" href="...yourpdf.pdf" target="_blank" 
type="application/octet-stream" download="yourpdf.pdf">click here</a>.</p>

jQuery (le code JavaScript pur serait plus verbeux) qui simule un clic sur un lien après un petit délai :

var delay = 3000;
window.setTimeout(function(){$('#downloadLink')[0].click();},delay);

Pour rendre ce système plus robuste, vous pourriez ajouter la détection de la fonctionnalité HTML5 et, si elle n'est pas présente, utiliser la méthode suivante window.open() pour ouvrir une nouvelle fenêtre avec le fichier.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X