2012-09-13 20 views
4

我是新手,所以我會盡我所能解釋我遇到的問題。如果有什麼我遺漏或不清楚的,我提前道歉。下載用PHP提供的大型(ish)zip文件被連接速度慢的人損壞

我正在爲我的根目錄之外的81MB zip文件提供預先驗證的人員。我一直在收到有關損壞的下載或無法完成下載的報告。如果我模擬慢速連接,我已經在我的機器上驗證了這一情況。

我在共享主機上運行Apache-Coyote/1.1。

我收到網絡超時錯誤。我認爲我的主機可能會在下載時間過長的情況下殺死下載內容,但是他們沒有通過任何方式驗證。

我以爲我可能會遇到內存限制或時間限制,所以我的主機安裝了Apache模塊XSendFile。我認爲處理驗證後正在設置這樣的下載文件中的標題:

<?php 
set_time_limit(0); 
$file = '/absolute/path/to/myzip/myzip.zip'; 

header("X-Sendfile: $file"); 
header("Content-type: application/zip"); 
header('Content-Disposition: attachment; filename="' . basename($file) . '"'); 

任何幫助或建議,將不勝感激。謝謝!

+0

您是否嘗試發送使用文件'Content-Type:application/octet-stream'而不是「zip」?我還建議查看https://tn123.org/mod_xsendfile/並確保/向主機驗證設置是否正確。 –

+0

事實證明,我的共享主機環境是問題所在。我的主機無法正確安裝XSendFile,並在10分鐘後關閉,因此連接速度慢的用戶正在獲取部分下載/網絡超時。轉向VPS解決了這個問題。 – stringerbell

回答

2

我建議考慮看看此評論:

http://www.php.net/manual/en/function.readfile.php#99406

特別是,如果你使用Apache。如果不是以上鍊接中的代碼應該是有幫助的:

我真的很大的文件被髮送到客戶端與下載速度非常慢,我開始遇到麻煩。在這些情況下, 腳本將超時,下載將以 不完整文件終止。我死定了禁止腳本超時 - 任何 時間是一個編程問題的解決方案,你做的 有什麼問題 - 所以我試圖根據文件的大小 縮放超時。這最終失敗,因爲它是 不可能預測的最終用戶將在 下載文件的速度,所以它真的只是一個最好的猜測,所以 不可避免地我們仍然得到腳本超時的報告。

然後我跨越奇妙Apache模塊稱爲mod_xsendfile絆(https://tn123.org/mod_xsendfile/(二進制)或 https://github.com/nmaier/mod_xsendfile(源))。該模塊 基本上監視輸出緩衝區是否存在特殊的 標題,並且當它發現它們時,它會觸發apache發送它自己的文件 ,就好像用戶直接請求文件一樣。 PHP 處理在此時暫停,因此不管文件的大小或客戶端的下載速度如何,都不會出現超時錯誤。並且客戶端 可以獲得Apache發送文件的全部好處,例如 準確的文件大小報告和下載狀態欄。

我終於結束了與該代碼太長,張貼在這裏,但一般是採用mod_xsendfile模塊,如果它存在,如果沒有 腳本回退到使用我最初發布的代碼。在https://gist.github.com/854168

編輯

可以 找到一些示例代碼正好有代碼,做了「分塊」 Link to Original Code參考:

<?php 
function readfile_chunked ($filename,$type='array') { 
    $chunk_array=array(); 
    $chunksize = 1*(1024*1024); // how many bytes per chunk 
    $buffer = ''; 
    $handle = fopen($filename, 'rb'); 
    if ($handle === false) { 
    return false; 
    } 
    while (!feof($handle)) { 
     switch($type) 
     { 
      case'array': 
      // Returns Lines Array like file() 
      $lines[] = fgets($handle, $chunksize); 
      break; 
      case'string': 
      // Returns Lines String like file_get_contents() 
      $lines = fread($handle, $chunksize); 
      break; 
     } 
    } 
    fclose($handle); 
    return $lines; 
} 
?>