2013-04-08 10 views
7

Ho un problema che è aumentato molte volte in SO, ma non riesco a trovare la soluzione per il mio! Sto cercando di consegnare un file pdf al client senza che si apra nel browser, il file viene scaricato ma è corrotto quando lo apro e mancano alcuni byte dal file originale. Ho provato diversi metodi per scaricare il file, ma ti mostrerò solo l'ultimo che ho usato e spero di ricevere un feedback.Force Download di un file PDF, file corrotto

Ho anche aperto il PDF scaricato in un editor di testo e non ci sono errori di php in cima a quello che posso vedere!

Sono anche consapevole del fatto che readfile() è molto più veloce ma a scopo di test sono disperato per far funzionare qualsiasi cosa quindi ho usato l'approccio while (! Feof())!

comunque abbastanza sconnesso, ecco il codice (tratto da 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); 

anche sottolineare è stata la differenza di dimensione del file:

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

Hai provato 'readfile()'? – barbashov

+0

@ DavidC799: Se vuoi discutere la risposta di una domanda precedente, lascia un commento lì. Non solo inserire qui un codice e dirci "non funziona". Tenete a mente, solo qualcun altro ha accettato quella risposta, non deve significare che il codice deve funzionare anche per voi. E per scopi di test, si prega di ridurre il codice al minimo indispensabile per provocare il problema. Per esempio. nessuna funzione, solo un nome di file hardcoded. Usa readfile. – hakre

+0

@barbashov sì, ho provato diversi metodi. – DavidC799

risposta

7

Assicurarsi che non sta eseguendo alcuna compressione i gestori di buffer di output, come ob_gzhandler. Avevo un caso simile e ho dovuto disabilitare il buffering dell'output perché funzionasse correttamente

+0

Davvero io sono! Ora che ne parli, ho visto qualcun altro menzionarlo in un altro post. Proverò alcune cose e ti farò sapere come va. Ci scusiamo per il fastidio! – DavidC799

+0

Successo! Molte grazie per il vostro aiuto, sempre qualcosa di molto semplice :( – DavidC799

+0

@ DavidC799: Bene, leggete solo le altre domande, la maggior parte delle risposte sul sito web è già solo bisogno di trovarle;) – hakre

6

Si sta utilizzando il ob_gzhandler sul buffer di output.

Funziona con gzencoding blocchi di output. L'output è quindi un flusso dei blocchi codificati.

Ogni chunk deve ottenere alcuni byte per essere codificati, quindi l'output è un po 'bufferizzato fino a quando sono disponibili abbastanza byte.

Tuttavia alla fine del tuo script scarti il ​​buffer rimanente invece di sciacquarlo.

Utilizzare ob_end_flush() anziché ob_clean() e il file passa completamente e non è danneggiato.

È necessario utilizzare la codifica di trasferimento di ob_gzhandler con file di caricamento che non presentano alcun problema quando non si distrugge il buffer di output prima che avrebbe potuto fare il suo lavoro.

Questo è anche lo stesso se qualsiasi altro buffer di uscita che funziona in blocchi sarebbe stato abilitato .

codice

Esempio:

$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: in realtà anche il ob_end_flush(); non è necessario, la parte importante è non calciare solo il buffer di uscita prima che avrebbe potuto fare è un lavoro)

+0

Posso confermare che il codice di hakre funziona come previsto; grazie per la spiegazione dettagliata – periklis

+0

Inoltre ho appena controllato il sorgente readfile() in PHP e dovresti (se puoi) usarlo sempre invece di fare proprio il fopen/buffered read come nella domanda. 'readfile()' è di gran lunga superiore per gli output di download dei file perché può sfruttare i vantaggi del SAPI che non sono possibili nel codice userland. – hakre

-1

I combattuto con l'uso di content-disposition per spingere un download di PDF per due giorni prima di trovare una soluzione al mio problema. I miei file PDF erano anche più piccoli e corrotti - tuttavia, potevo aprirli in Windows Preview - solo Adobe. Dopo una lunga risoluzione dei problemi, ho scoperto che Adobe si aspetta il% PDF nei primi 1024 byte del file. Prima di creare le intestazioni stavo facendo tutti i miei controlli sui tipi di file nel mio codice php. Ho eliminato la maggior parte del codice prima che le intestazioni e il mio file PDF fossero corretti.

Potrebbe non essere la sua creazione allo stesso modo ho fatto, ma potrebbe essere lo stesso problema:

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