Как ускорить файл_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-адрес.

Это медленно, потому что file_get_contents() читает весь файл в $page , PHP ждет, пока файл будет получен до вывода содержимого. Итак, что вы делаете: загрузка всего файла на стороне сервера, а затем вывод его в виде одной огромной строки.

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-заголовки ответов, которые будут первыми несколькими строками, потому что, поскольку вы делаете необработанный запрос, вы получите исходный ответ с включенными заголовками. Если вы выведете заголовки ответов, вы получите поврежденный файл.

Как объяснил @MrCode, сначала загрузить файл на ваш сервер, а затем передать его клиенту, конечно же, придется удвоить время загрузки. Если вы хотите напрямую передать файл клиенту, используйте readfile .

В качестве альтернативы подумайте, не можете ли вы просто перенаправить клиента на URL-адрес файла с помощью header("Location: $url") чтобы клиент мог получить файл непосредственно из источника.

Вместо того, чтобы загружать весь файл перед его выпуском, рассмотрите возможность его потоковой передачи следующим образом:

 $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'); 

Другой вариант – использование внутренних переадресаций и предоставление прокси-сервера веб-сервера для вас. Это освободит PHP, чтобы сделать что-то еще. См. Также мое сообщение о X-Sendfile и друзьях .