2012-12-03 7 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

ファイルのサイズは何秒で、フェッチするのに何秒かかりますか? 1つを他のもので割ると、帯域幅がわかります。予期せず遅い場合は、あなたまたは遠隔地のどちらかがさらに必要です! –

答えて

8

file_get_contents()がファイル全体を$pageに読み込むため、PHPはファイルを受信するのを待ってからコンテンツを出力します。つまり、サーバー側でファイル全体をダウンロードし、それを単一の大きな文字列として出力します。

file_get_contents()は、リモートファイルのストリーミングまたはグラバーオフセットをサポートしていません。オプションは、fsockopen()でrawソケットを作成し、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で説明したように、最初にファイルをサーバーにダウンロードしてからクライアントに渡すと、ダウンロード時間は2倍になります。ファイルをクライアントに直接渡す場合は、readfileを使用します。

また、あなたは、単にソースから直接ファイルを取得することができますheader("Location: $url")ので、クライアントを使用してファイルのURLにクライアントをリダイレクトすることができない場合を考えます。あなたは大胆している場合

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

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

は、あなたも試みることができる(しかし、それは間違いなく、実験です):

+0

'readfile'を使用しているときにリクエストのユーザエージェントを変更できますか? – think123

+0

これは '$ context'リソースもサポートしています。 – deceze

2

は、代わりにそれを出力する前に、ファイル全体をダウンロードするので、このようにそれをストリーミング考える

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

もう1つの方法は、内部リダイレクトを使用して、Webサーバープロキシを要求することです。それはPHPに何か他のことをさせるものです。 my post regarding X-Sendfile and friendsも参照してください。

関連する問題