2010-02-18 46 views
0

我有以下腳本,讓訪客下載文件:問題與下載:緩慢和/或失敗

header('Content-Type: application/octet-stream'); 
header('Content-Transfer-Encoding: binary'); 
header('Content-Disposition: attachment; filename=' . $fileName); 
header('Content-Length: ' . filesize($filePath)); 
header('Content-Description: Download'); 
header('Cache-Control: private'); 
header('Pragma: no-cache'); 
header('Expires: 0'); 

readfile($filePath); 
exit(); 

它沒有很好地工作。 (我也把文件名放在引號中,結果相同)。

它表現得非常慢,有時下載甚至停止。特別是在Opera中,99%的下載停止。有時它甚至立即顯示99%完成,然後開始下載並停止在大約34%。

服務器是共享主機,Mac OS X服務器。

隨着使用Firefox的Live HTTP頭插件,我已經注意到了服務器將aditional的頭到響應:

HTTP/1.1 200 OK 
Date: Thu, 18 Feb 2010 09:27:25 GMT 
Server: Apache 
X-Powered-By: PHP/5.2.12 
Content-Transfer-Encoding: binary 
Content-Disposition: attachment; filename=test.psd 
Content-Length: 398635 
Content-Description: Download 
Cache-Control: private 
Pragma: no-cache 
Expires: 0 
Content-Encoding: gzip // <-- expecially this one, 
Vary: Accept-Encoding // <-- this one, 
MS-Author-Via: DAV // <-- and this one 
Keep-Alive: timeout=10, max=100 
Connection: Keep-Alive 
Content-Type: application/octet-stream 

難道這是問題的原因是什麼?

當我在本地主機上運行腳本時,一切正常。另外,當我直接從這個主機上下載文件時,速度也很好,流暢。

我對這一個真的很無知。你的幫助是明確的。先謝謝你。

UPDATE:

我想我已經到了瓶頸狹窄的問題。網絡服務器自動gzip壓縮輸出。當我從我的PHP腳本中刪除Content-Length標題時,一切開始下載流暢。這是有道理的:Content-Length的值與實際的gzip輸出不再匹配。在PHP中,我讀取未壓縮的文件大小以設置Content-Length頭,但之後,Apache壓縮它,這可能是瀏覽器窒息的地方。

我會在網絡服務器自動gzip壓縮輸出時,關注如何設置正確的Content-Length標題大小的問題。

回答

0

我已經縮小了問題的瓶頸。網絡服務器自動gzip壓縮輸出。當我從我的PHP腳本中刪除Content-Length標題時,一切都開始順利下載。這是有道理的:Content-Length的值與實際的gzip輸出不再匹配。在PHP中,我讀取未壓縮的文件大小來設置Content-Length標頭,但之後,Apache壓縮它,這可能是瀏覽器窒息的地方。

0

嘗試取消設置gzip-Content-Encoding。

在腳本的一開始就使用ob_start();在設置標題之前,使用@ob_end_clean();並緊跟其後,明確設置header("Content-Encoding:");以嘗試解除可能會出現的任何gzip-Encoding。 在文件位置末尾@ob_end_flush();

輸出緩衝功能很方便,使標題設置更安全,但可能與您的問題無關。我只記得在一個設置中遇到了問題,其中封裝的PHP代碼使用ob_gzhandler,我需要將其解除。

+0

嗨initall,謝謝你的迴應。我想我已經把問題縮小了。恐怕我無法覆蓋Content-Encoding標頭,因爲它是由網絡服務器設置的。換句話說,我相信Apache服務器被配置爲自動gzip壓縮輸出。所以,現在當我從我的PHP腳本中移除「Content-Length」頭時,所有工作都正常。這是有道理的,因爲PHP設置的內容長度與gzip壓縮文件的實際內容長度不再一致。這是瀏覽器可能窒息的地方。 – 2010-02-18 10:18:48

+0

好的,聽起來很合理。爲了避免壓縮兩次,我也做過一次類似於主腳本頂部的操作: 'if(extension_loaded('zlib')&&(!(bool)ini_get('zlib.output_compression'))){ ob_start( 'ob_gzhandler'); } else { ob_start(); }' – initall 2010-02-18 11:11:15

0

我使用下面的代碼,它的工作原理。告訴你,我沒undersyand但正確的是我送的所有頭實話,我仍然沒有進行調查的時候,我發現瞭解釋:

來源:

http://www.opendesigns.org/forum/discussion/1437/php-download-counter/#pgbottom http://www.webdeveloper.com/forum/showthread.php?t=115815&highlight=PHP+download+counter http://php.net/manual/en/function.header.php#83384

無論如何它的工作原理:

/* 
    TODO: still to be read and better understood. 
    */ 

    //no caching (I don't uderstand what is this part useful for) 
    header("Pragma: public"); //? 
    header("Expires: 0"); //? 
    header("Cache-Control: must-revalidate, post-check=0, pre-check=0"); //? 
    header("Cache-Control: private", false); //? 

    //sending download file 
    header("Content-Type: application/octet-stream"); //application/zip can use application/octet-stream that is more generic it works because in now days browsers are able to detect file anyway 
    header("Content-Disposition: attachment; filename=\"" . basename($file_serverfullpath) . "\""); //ok 
    header("Content-Transfer-Encoding: binary"); //? 
    header("Content-Length: " . filesize($file_serverfullpath)); //ok 
    readfile($file_serverfullpath);