web-dev-qa-db-fra.com

Comment faire PDF fichier téléchargeable en 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 lorsque l’utilisateur clique sur ce lien puis

  • Si l'utilisateur a installé Adobe Acrobat, il ouvre le fichier dans la même fenêtre de navigateur que dans Adobe Reader.
  • Si Adobe Acrobat n'est pas installé, il apparaîtra à l'utilisateur pour le téléchargement du fichier.

Mais je veux qu'il soit toujours téléchargé par l'utilisateur, que "Adobe Acrobat" soit installé ou non.

S'il vous plaît dites-moi comment je peux faire ça?

112
Prashant

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 génère un en-tête personnalisé, ouvre le PDF (coffre-fort binaire) et imprime les données dans le navigateur de l'utilisateur. Ils peuvent ensuite choisir d'enregistrer le PDF malgré les paramètres de leur 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 exécuter des vérifications de sécurité sur la variable "fichier" pour empêcher les gens de voler vos fichiers tels que ne pas accepter les extensions de fichier, refuser les barres obliques, ajouter .pdf à la valeur

113
TravisO

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

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

newfilename est le nom de fichier suggéré pour que l'utilisateur puisse enregistrer le fichier. Ou alors, le nom de fichier sur le serveur sera défini par défaut si vous le laissez vide, comme ceci:

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

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

Vérifiez la compatibilité ici: http://caniuse.com/#feat=download

171
T_D

Ne faites pas une boucle à travers chaque ligne de fichier . Utilisez readfile à 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 de nettoyer votre variable get car quelqu'un pourrait télécharger des fichiers php ...

48
Alex V

Au lieu d'utiliser un script PHP pour lire et vider le fichier, il est plus pratique de réécrire l'en-tête en utilisant .htaccess. Cela conservera une URL "sympa" (myfile.pdf au lieu de download.php?myfile).

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

J'ai trouvé un moyen de le faire avec HTML et JavaScript/jQuery classiques qui se dégradent avec élégance. 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 (du code JavaScript pur serait plus détaillé) qui simule un clic sur le lien après un petit délai:

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

Pour rendre cela plus robuste, vous pouvez ajouter la détection de fonctionnalités HTML5 et si ce n’est pas là, utilisez window.open() pour ouvrir une nouvelle fenêtre avec le fichier.

14
Alex W

Il existe un moyen plus simple en HTML5: Ajouter un attribut Download

Il est supporté par la plupart des navigateurs modernes.

<a download href="file.pdf">Download PDF</a> 
5
tawsif torabi

C'est la clé:

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

Le type de contenu application/x-pdf-document ou application/pdf est envoyé lors de l'envoi du fichier PDF. Adobe Reader définit généralement le gestionnaire pour ce type MIME afin que le navigateur transmette le document à Adobe Reader lorsque l'un des types PDF MIME est reçu.

5
Sudden Def

Je sais que je suis très tard pour répondre à cette question mais j'ai trouvé un moyen de le faire en javascript.

function downloadFile(src){
    var link=document.createElement('a');
    document.body.appendChild(link);
    link.href= src;
    link.download = '';
    link.click();
}
3
Shivek Parmar

Essaye ça:

<a href="pdf_server_with_path.php?file=pdffilename&path=http://myurl.com/mypath/">Download my eBook</a>

Le code à l'intérieur de pdf_server_with_path.php est:

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

$file = $_GET["file"] .".pdf";
$path = $_GET["path"];
$fullfile = $path.$file;

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

si vous avez besoin de limiter le taux de téléchargement, utilisez ce code!

<?php
$local_file = 'file.Zip';
$download_file = 'name.Zip';

// set the download rate limit (=> 20,5 kb/s)
$download_rate = 20.5;
if(file_exists($local_file) && is_file($local_file))
{
header('Cache-control: private');
header('Content-Type: application/octet-stream');
header('Content-Length: '.filesize($local_file));
header('Content-Disposition: filename='.$download_file);

flush();
$file = fopen($local_file, "r");
while(!feof($file))
{
    // send the current file part to the browser
    print fread($file, round($download_rate * 1024));
    // flush the content to the browser
    flush();
    // sleep one second
    sleep(1);
}
fclose($file);}
else {
die('Error: The file '.$local_file.' does not exist!');
}

?>

Pour plus d'informations cliquez ici

0
Mehran Hooshangi

J'ai résolu le mien en utilisant toute l'URL du fichier PDF (au lieu de simplement mettre le nom ou l'emplacement du fichier dans href): un href = "domaine. fr/pdf/nom_fichier.pdf" 

0
Mark Allena
<!DOCTYPE html>  
<html xmlns="http://www.w3.org/1999/xhtml">  
<head>  
    <title>File Uploader</title>  
    <script src="../Script/angular1.3.8.js"></script>  
    <script src="../Script/angular-route.js"></script>  
    <script src="../UserScript/MyApp.js"></script>  
    <script src="../UserScript/FileUploder.js"></script>  
    <>  
        .percent {  
            position: absolute;  
            width: 300px;  
            height: 14px;  
            z-index: 1;  
            text-align: center;  
            font-size: 0.8em;  
            color: white;  
        }  

        .progress-bar {  
            width: 300px;  
            height: 14px;  
            border-radius: 10px;  
            border: 1px solid #CCC;  
            background-image: -webkit-gradient(linear, left top, left bottom, from(#6666cc), to(#4b4b95));  
            border-image: initial;  
        }  

        .uploaded {  
            padding: 0;  
            height: 14px;  
            border-radius: 10px;  
            background-image: -webkit-gradient(linear, left top, left bottom, from(#66cc00), to(#4b9500));  
            border-image: initial;  
        }  
    </>  
</head>  
<body ng-app="MyApp" ng-controller="FileUploder">  
    <div>  
        <table ="width:100%;border:solid;">  
            <tr>  
                <td>Select File</td>  
                <td>  
                    <input type="file" ng-model-instant id="fileToUpload" onchange="angular.element(this).scope().setFiles(this)" />  
                </td>  
            </tr>  
            <tr>  
                <td>File Size</td>  
                <td>  
                    <div ng-repeat="file in files.slice(0)">  
                        <span ng-switch="file.size > 1024*1024">  
                            <span ng-switch-when="true">{{file.size / 1024 / 1024 | number:2}} MB</span>  
                            <span ng-switch-default>{{file.size / 1024 | number:2}} kB</span>  
                        </span>  
                    </div>  
                </td>  
            </tr>             
            <tr>  
                <td>  
                    File Attach Status  
                </td>  
                <td>{{AttachStatus}}</td>  
            </tr>  
            <tr>  
                <td>  
                    <input type="button" value="Upload" ng-click="fnUpload();" />  
                </td>  
                <td>  
                    <input type="button" value="DownLoad" ng-click="fnDownLoad();" />  
                </td>  
            </tr>  
        </table>  
    </div>  
</body>  
</html>   
0
user11021789

Voici une approche différente. Je préfère utiliser plutôt la prise en charge du navigateur, ou l’adresser au niveau de la couche application, pour utiliser la logique du serveur Web.

Si vous utilisez Apache et pouvez mettre un fichier .htaccess dans le répertoire approprié, vous pouvez utiliser le code ci-dessous. Bien sûr, vous pouvez aussi mettre ceci dans httpd.conf, si vous y avez accès.

<FilesMatch "\.(?i:pdf)$">
  Header set Content-Disposition attachment
</FilesMatch>

La directive FilesMatch est juste une regex, elle peut donc être définie avec autant de précision que vous le souhaitez ou vous pouvez ajouter d'autres extensions.

La ligne d'en-tête fait la même chose que la première ligne des scripts PHP ci-dessus. Si vous devez également définir les lignes Content-Type, vous pouvez le faire de la même manière, mais je n'ai pas trouvé cela nécessaire.

0
Evan Donovan