2012-12-03 64 views
14

這裏是我的代碼:如何加快file_get_contents?

$language = $_GET['soundtype']; 
$word = $_GET['sound']; 
$word = urlencode($word); 
if ($language == 'english') { 
    $url = "<the first url>"; 
} else if ($language == 'chinese') { 
    $url = "<the second url>"; 
} 
$opts = array(
    'http'=>array(
    'method'=>"GET", 
    'header'=>"User-Agent: <my user agent>" 
) 
); 
$context = stream_context_create($opts); 
$page = file_get_contents($url, false, $context); 
header('Content-Type: audio/mpeg'); 
echo $page; 

但我發現這非常運行緩慢。

是否有任何可能的優化方法?

注意:$url是一個遠程URL。

+2

是$ url本地路徑還是http:// url? – Intrepidd

+0

@Intrepidd是的,對不起,一個遠程URL。 – think123

+1

文件的大小是多少,需要多長時間才能獲取?將另一個分開,你會發現帶寬。如果出乎意料地很慢,您或者遠程方需要更多! –

回答

8

由於file_get_contents()將整個文件讀入$page,因此輸出內容前等待文件接收。所以你要做的是:在服務器端下載整個文件,然後把它作爲一個單一的大字符串輸出。

file_get_contents()不支持流式傳輸或抓取遠程文件的偏移量。一個選項是創建一個具有fsockopen()的原始套接字,執行HTTP請求,並在讀取每個塊時讀取循環中的響應,並將其輸出到瀏覽器。這將會更快,因爲文件將被流式傳輸。從手動

實施例:

$fp = fsockopen("www.example.com", 80, $errno, $errstr, 30); 
if (!$fp) { 
    echo "$errstr ($errno)<br />\n"; 
} else { 

    header('Content-Type: audio/mpeg'); 

    $out = "GET/HTTP/1.1\r\n"; 
    $out .= "Host: www.example.com\r\n"; 
    $out .= "Connection: Close\r\n\r\n"; 
    fwrite($fp, $out); 
    while (!feof($fp)) { 
     echo fgets($fp, 128); 
    } 
    fclose($fp); 
} 

上面是循環而仍有內容可用時,在其上讀出128個字節每次迭代,然後將其輸出到瀏覽器。同樣的原則也適用於你正在做的事情。你需要確保你不輸出響應HTTP頭,這將是頭幾行,因爲你正在做一個原始請求,你將得到包含頭的原始響應。如果輸出響應頭文件,則最終會出現損壞的文件。

+1

你能舉個例子嗎? 'fsockopen()'對我來說是希臘語。 – think123

+0

@ think123增加了一個例子 – MrCode

+0

很好的解釋! – jan267

2

正如@MrCode所解釋的,首先將文件下載到服務器,然後將它傳遞給客戶端當然會導致下載時間加倍。如果您想直接將文件傳遞到客戶端,請使用readfile

另外,想一想如果你不能簡單地客戶重定向到使用header("Location: $url")所以客戶端可以直接從源獲得該文件的文件URL。

+0

使用'readfile'時你能改變請求的User Agent嗎? – think123

+0

它也支持'$ context'資源,所以是的。 – deceze

2

相反輸出之前下載整個文件,考慮流出來是這樣的:

$in = fopen($url, 'rb', false, $context); 
$out = fopen('php://output', 'wb'); 

header('Content-Type: video/mpeg'); 
stream_copy_to_stream($in, $out); 

如果你敢,你甚至可以嘗試(但絕對實驗):

header('Content-Type: video/mpeg'); 
copy($url, 'php://output'); 

另一個選擇是使用內部重定向,並讓您的Web服務器代理爲您提供請求。這將釋放PHP來做其他事情。另見my post regarding X-Sendfile and friends