2013-04-08 18 views
7

Ich habe ein Problem, das viele Male auf SO gestiegen ist, aber ich kann nicht scheinen, die Lösung zu mir zu finden! Ich versuche, eine pdf-Datei an den Client zu liefern, ohne dass es im Browser geöffnet wird, die Datei wird heruntergeladen, aber es ist beschädigt, wenn ich es öffne und mir einige Bytes aus der Originaldatei fehlen. Ich habe mehrere solcher Methoden ausprobiert, um die Datei herunterzuladen, aber ich werde Ihnen nur das Neueste zeigen, das ich benutzt habe und hoffentlich ein Feedback bekommen.Erzwingen Herunterladen einer PDF-Datei, beschädigte Datei

Ich habe auch die heruntergeladene PDF in einem Texteditor geöffnet und es gibt keine PHP-Fehler an der Spitze, die ich sehen kann!

Ich bin mir auch bewusst, dass readfile() ist viel schneller, aber zu Testzwecken bin ich verzweifelt, um alles funktioniert so dass ich die while (! Feof()) Ansatz verwendet!

Auf jeden Fall genug Wandern, heres der Code (aus why my downloaded file is alwayes damaged or corrupted?):

$file  = __DIR__ . '/reports/somepdf.pdf'; 
$basename = basename($file); 
$length = sprintf("%u", filesize($file)); 

header('Content-Description: File Transfer'); 
header('Content-Type: application/octet-stream'); 
header('Content-Disposition: attachment; filename="' . $basename . '"'); 
header('Content-Transfer-Encoding: binary'); 
header('Connection: Keep-Alive'); 
header('Expires: 0'); 
header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); 
header('Pragma: public'); 
header('Content-Length: ' . $length); 

ob_clean(); 
set_time_limit(0); 
readfile($file); 

auch zu beachten, war der Unterschied in der Dateigröße:

Original: 351,873 bytes 
Downloaded: 329,163 bytes 
+1

Haben Sie versucht, 'readfile()'? – barbashov

+0

@ DavidC799: Wenn Sie die Antwort einer früheren Fragen diskutieren möchten, hinterlassen Sie einen Kommentar dort. Nicht einfach hier einen Code eingeben und uns sagen "es funktioniert nicht". Denken Sie daran, dass nur jemand anderes diese Antwort akzeptiert hat, es darf nicht bedeuten, dass der Code auch für Sie funktionieren muss. Und zu Testzwecken reduzieren Sie bitte den Code auf das Nötigste, um das Problem zu provozieren. Z.B. keine Funktion, nur ein fest codierter Dateiname. Verwenden Sie readfile. – hakre

+0

@barbashov ja ich habe verschiedene Methoden ausprobiert. – DavidC799

Antwort

7

Stellen Sie sicher, Sie laufen keine Kompression Ausgabepufferhandler wie ob_gzhandler. Ich hatte einen ähnlichen Fall und ich musste die Ausgangspufferung deaktivieren, damit dies richtig funktioniert

+0

Ja tatsächlich bin ich! Jetzt, wo du es erwähnst, habe ich gesehen, dass jemand anderes das in einem anderen Post erwähnt hat. Versuche ein paar Dinge und lass dich wissen wie es geht. Tut mir leid wegen dem Ärger! – DavidC799

+0

Erfolg! Vielen Dank für Ihre Hilfe, immer etwas so einfaches :( – DavidC799

+0

@ DavidC799: Nun, lesen Sie einfach die anderen Fragen, die meisten Antworten auf der Website bereits müssen Sie nur finden;) – hakre

6

Sie verwenden die ob_gzhandler auf dem Ausgabepuffer.

Es funktioniert durch Generieren von Chunks der Ausgabe. Die Ausgabe ist dann ein Strom der codierten Stücke.

Jeder Chunk muss einige Bytes erhalten, um codiert zu werden, daher wird die Ausgabe ein wenig gepuffert, bis genug Bytes verfügbar sind.

Am Ende des Skripts verwerfen Sie jedoch den verbleibenden Puffer, anstatt ihn zu löschen.

Verwenden Sie ob_end_flush() anstelle von ob_clean() und die Datei wird vollständig durch und nicht beschädigt.

Sie müssen die Transfercodierung von ob_gzhandler mit Datei-Uploads verwenden, die keine Probleme haben, wenn Sie den Ausgabepuffer nicht zerstören, bevor es seine Arbeit getan haben könnte.

Dies ist auch das Gleiche, wenn eine andere Ausgabepufferung, die chunked funktioniert, aktiviert wäre.

Beispielcode:

$file  = __DIR__ . '/somepdf.pdf'; 
$basename = basename($file); 
$length = sprintf("%u", filesize($file)); 

header('Content-Description: File Transfer'); 
header('Content-Type: application/octet-stream'); 
header('Content-Disposition: attachment; filename="' . $basename . '"'); 
header('Content-Transfer-Encoding: binary'); 
header('Connection: Keep-Alive'); 
header('Expires: 0'); 
header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); 
header('Pragma: public'); 
header('Content-Length: ' . $length); 

ob_end_flush(); // <--- instead of ob_clean() 

set_time_limit(0); 
readfile($file); 

return; 

(FYI: eigentlich sogar die ob_end_flush(); nicht notwendig ist, ist der wichtige Teil einfach nicht, um die Ausgabe-Puffer treten, bevor es es ist Arbeit getan haben könnte)

+0

Ich kann bestätigen, dass hakres Code funktioniert wie erwartet; danke für die ausführliche Erklärung – periklis

+0

Auch ich habe nur readfile() source in PHP überprüft und Sie sollten (wenn Sie können) immer es verwenden, anstatt das fopen/gepuffertes Lesen als in der Frage zu besitzen. 'readfile()' ist bei Datei-Download-Ausgaben weit überlegen, da es Vorteile im SAPI nutzen kann, die im Userland-Code nicht möglich sind. – hakre

-1

I gekämpft mit Content-Disposition für einen PDF-Download für zwei Tage, bevor eine Lösung für mein Problem zu finden. Meine PDF-Dateien waren auch kleiner und korrupt - aber ich konnte sie in Windows Preview öffnen - nur nicht Adobe. Nach langer Fehlersuche habe ich festgestellt, dass Adobe das% PDF in den ersten 1024 Byte der Datei erwartet. Ich habe alle meine Dateitypen in meinem PHP-Code überprüft, bevor ich die Header erstellt habe. Ich nahm den Großteil des Codes heraus, bevor die Header und meine PDF-Datei repariert wurde.

Sie könnten es nicht auf die gleiche Art und Weise habe ich sein Einstellung, aber es könnte das gleiche Problem sein:

http://helpx.adobe.com/acrobat/kb/pdf-error-1015-11001-update.html

Verwandte Themen