2013-02-02 184 views
3

我正在通過PHP腳本向用戶下載URL。當使用readfile()時,我獲得了我的連接可以支持的最大下載速度(約2.5MB/s),但是當我使用fopen, fread, fclose路由時,下載速度非常非常慢(約1-2KB/s)。下載速度比讀取文件慢很多

這裏是我的代碼:

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'); 
header('Pragma: public'); 
header('Content-Length: ' . $filesize); 
ob_clean(); 
flush(); 

$file = fopen($url, 'rb'); 

while(!feof($file)) { 
    echo fread($file, 2014); 
} 

和ReadFile的代碼只是readfile($link);

我不能只使用readfile()功能的原因有兩個,一個是我想限制用戶的下載速度(我可以只讀取如此多的數據與fread做),我也想跟蹤多少用戶正在下載(我可以用readfile()來做到這一點,但它不會計算部分下載)。

有誰知道爲什麼會發生這種情況,或者我可以如何解決它?據我所知readfile()只是fopen, fread and fclose的包裝,所以我沒有得到什麼問題。

編輯:結束與cURL爲此。

$curl = curl_init(); 
$options = array(
    CURLOPT_URL => $rdLink, 
    CURLOPT_FAILONERROR => true, 
    CURLOPT_BINARYTRANSFER => true, 
    CURLOPT_RETURNTRANSFER => true, 
    CURLOPT_WRITEFUNCTION => 'readResponse' 
); 
curl_setopt_array($curl, $options); 

if(!curl_exec($curl)) { 
    header('Location: http://whatever.com'); 
    exit; 
} 
curl_close($curl); 

function readResponse($ch, $data) { 
    $length = mb_strlen($data, '8bit'); 

    echo $data; 

    return $length; 
} 
+0

你真的需要輸出緩衝嗎?試試'ob_end_flush();' – Boann

+0

我不確定,我從別的地方得到了這段代碼,它有輸出緩衝。我應該在哪裏放置'ob_end_flush();'? –

+0

把它放在任何地方,然後再開始寫作。 – Boann

回答

2

使用stream_context_create()stream_get_contents()

$context = stream_context_create(); 
$file = fopen($url, 'rb', FALSE, $context); 
while(!feof($file)) 
{ 
    //usleep(1000000); 
    echo stream_get_contents($file, 2014); 
} 

您也可以嘗試使文件讀取的長度,且投入usleep()函式慢執行。 無論如何,流功能似乎被推薦超過fread的最新版本的PHP。 您可能還想在fread()或stream_get_contents()的前面加上@來抑制任何錯誤,至少在生產中是這樣。沒有它,有點不幸,而且你有一個損壞的文件。

+1

這是一個猜測,還是有一個原因,它應該更快?我很想看看替代品的一些基準。 –

+0

這需要一些解釋。如果stream_get_contents速度更快,那麼爲什麼fread不會執行stream_get_contents的操作? – Boann

+1

這是基於知道stream_get_contents()不超時並基於服務器的條件處理它知道它可以執行的操作。我只是用一個沒有讀取長度的大文件嘗試每個文件,fread超時導致內部服務器錯誤,並且stream_get_contents工作。但隨着2014年的閱讀時長平均在相同的執行時間。 我想讓我的評論與其他人一起,但我沒有收到'添加評論'按鈕。你的回覆之後是第一次出現,但僅限於此塊。 –

0

它可能是緩衝(或者甚至是速率限制)在PHP或Apache的某個地方。嘗試改變:

while(!feof($file)) { 
    echo fread($file, 2014); 
} 

爲:(該@前綴是因爲他們可能會抱怨空的緩衝器)

while(!feof($file)) { 
    $s=fread($file, 2014); 
    if($s===false)break; //Crude 
    echo $s; 
    @ob_flush();@flush(); 
} 

正如mr.freshwater說,你應該有錯誤檢查在你的fread電話上,所以我在上面添加了一些基本的東西。

0

原因是2014.OS獲得4096字節的數據部分非常快,然後其他人。但是如果你寫了2014,那麼OS會嘗試從文件中讀取一個字節的數據來計算它。這就是爲什麼需要這麼長時間。更改2014年至4096年