这里是我的代码:
$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');
另一种选择是使用内部重定向,使您的Web服务器代理为你的请求。 这将腾出PHP做别的事情。 另请参见我的有关X-SENDFILE和朋友后 。