korrekte PHP-Header für den Download von PDF-Dateien

78

Ich habe wirklich Probleme damit, dass meine Anwendung ein PDF öffnet, wenn der Benutzer auf einen Link klickt.

Bisher leitet das Ankertag zu einer Seite weiter, die folgende Header sendet:

$filename='./pdf/jobs/pdffile.pdf;

$url_download = BASE_URL . RELATIVE_PATH . $filename;

header("Content-type:application/pdf");
header("Content-Disposition:inline;filename='$filename");
readfile("downloaded.pdf");

Das scheint nicht zu funktionieren. Hat jemand dieses Problem in der Vergangenheit erfolgreich gelöst?

Verwenden Sie Ihre Illusion zu
quelle
1
Tippfehler? Versuchen Sie, ein ' $filename='./pdf/jobs/pdffile.pdf';und in dieser Zeile header("Content-Disposition:inline;filename='$filename");fehlendes Anführungszeichen hinzuzufügen .
Funk Forty Niner
Wie / warum benutzt du $url_download?
Funk Forty Niner

Antworten:

135

Beispiel 2 auf w3schools zeigt, was Sie erreichen möchten .

<?php
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");
?>

Denken Sie auch daran,

Es ist wichtig zu beachten, dass header () aufgerufen werden muss, bevor eine tatsächliche Ausgabe gesendet wird (In PHP 4 und höher können Sie die Ausgabepufferung verwenden, um dieses Problem zu lösen.)

gat
quelle
Haha, wahr. Ich habe es nur erwähnt, weil es das gleiche Beispiel hatte.
Gat
Plus 1 für die Ausgabemitteilung.
Iamdash
5
Denken Sie daran, die einfachen Anführungszeichen um den Dateinamen zu entfernen. Wenn Sie filename = 'downloaded.pdf' verwenden, versuchen einige Browser, die Datei mit den Anführungszeichen im Dateinamen zu speichern. Ich habe dies kürzlich unter OSX erlebt.
Mattis
readfile()Sehr schlecht für große Dateien, denn wenn einige Benutzer herunterladen möchten, puffern alle heruntergeladenen Dateien auf dem Server-RAM !!!
mghhgm
1
Warum um alles in der Welt sollte ein PDF HTML-Tags haben?
delboy1978uk
29
$name = 'file.pdf';
//file_get_contents is standard function
$content = file_get_contents($name);
header('Content-Type: application/pdf');
header('Content-Length: '.strlen( $content ));
header('Content-disposition: inline; filename="' . $name . '"');
header('Cache-Control: public, must-revalidate, max-age=0');
header('Pragma: public');
header('Expires: Sat, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT');
echo $content;
Marin Vartan
quelle
1
Beachten Sie, dass das Laden des gesamten Dateiinhalts in eine Variable mit dem Speicherlimit kollidieren kann. Deshalb readfile()ist die bevorzugte Lösung.
Havenard
10

In Ihrem Code sind einige Dinge zu beachten.

Schreiben Sie zuerst diese Überschriften richtig. Sie werden niemals einen Server senden sehen Content-type:application/pdf, der Header ist Content-Type: application/pdfin Abständen mit großgeschriebenen Anfangsbuchstaben usw.

Der Dateiname in Content-Dispositionist nur der Dateiname, nicht der vollständige Pfad dazu, und obwohl ich nicht weiß, ob er obligatorisch ist oder nicht, wird dieser Name " nicht eingepackt '. Auch dein letzter 'fehlt.

Content-Disposition: inlineimpliziert, dass die Datei angezeigt und nicht heruntergeladen werden soll. Verwenden Sie attachmentstattdessen.

Stellen Sie außerdem die Dateierweiterung in Großbuchstaben ein, damit sie mit einigen Mobilgeräten kompatibel ist. ( Update : Ich bin mir ziemlich sicher, dass nur Brombeeren dieses Problem hatten, aber die Welt hat sich von diesen entfernt, so dass dies möglicherweise kein Problem mehr darstellt.)

Abgesehen davon sollte Ihr Code eher so aussehen:

<?php

    $filename = './pdf/jobs/pdffile.pdf';

    $fileinfo = pathinfo($filename);
    $sendname = $fileinfo['filename'] . '.' . strtoupper($fileinfo['extension']);

    header('Content-Type: application/pdf');
    header("Content-Disposition: attachment; filename=\"$sendname\"");
    header('Content-Length: ' . filesize($filename));
    readfile($filename);

Content-Lengthist optional, aber auch wichtig, wenn der Benutzer den Download-Fortschritt verfolgen und feststellen soll, ob der Download unterbrochen wurde. Wenn Sie es verwenden, müssen Sie jedoch sicherstellen, dass Sie nichts zusammen mit den Dateidaten senden. Stellen Sie sicher, dass vorher <?phpoder nachher absolut nichts ist ?>, nicht einmal eine leere Zeile.

Zufluchtsort
quelle
3
Sie benötigen das schließende Tag nicht ?>. In diesem Fall ist es besser, es zu entfernen.
Marcel Korpel
Ziemlich sicher, dass das Einschließen eines vom Header bereitgestellten Dateinamens in einfache Anführungszeichen das Herunterladen umfassend unterbricht. Wie Sie vorschlagen, macht dies einen großen Unterschied.
Brian C
4

Ich hatte kürzlich das gleiche Problem und das hat mir geholfen:

    header('Content-Description: File Transfer'); 
    header('Content-Type: application/octet-stream'); 
    header('Content-Disposition: attachment; filename="FILENAME"'); 
    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("PATH/TO/FILE")); 
    ob_clean(); 
    flush(); 
    readfile(PATH/TO/FILE);      
    exit();

Ich habe diese Antwort hier gefunden

haayek
quelle
2
ob_start (); an der Spitze sorgt für Datenkorruption
Dan Jay
1

Können Sie dies versuchen, readfilebenötigen Sie den vollständigen Dateipfad.

        $filename='/pdf/jobs/pdffile.pdf';            
        $url_download = BASE_URL . RELATIVE_PATH . $filename;            

        //header("Content-type:application/pdf");   
        header("Content-type: application/octet-stream");                       
        header("Content-Disposition:inline;filename='".basename($filename)."'");            
        header('Content-Length: ' . filesize($filename));
        header("Cache-control: private"); //use this to open files directly                     
        readfile($filename);
Krish R.
quelle
0

Sie müssen die Größe der Datei definieren ...

header('Content-Length: ' . filesize($file));

Und diese Zeile ist falsch:

Header ("Content-Disposition: Inline; Dateiname = '$ Dateiname");

Sie haben Quoten durcheinander gebracht.

Flash Thunder
quelle
4
Nein, Sie müssen die Größe der Datei nicht angeben. Das ist auch eine mögliche Quelle für Fehler.
Marcel Korpel
Abhängig von der PDF-Plugin-Version. Es ist sicher, es zu geben.
Flash Thunder
kann das nicht zum Laufen bringen. Was ist die $ file Variable, deren Größe ich teste? Ist es die Datei-URL ./pdf/jobs/pdftitle.pdf?
Verwenden Sie Ihre Illusion zu
Ja, es ist der Speicherort der Datei ... Vielleicht vermasseln Sie Pfade? versuche den absoluten Weg anzugeben.
Flash Thunder