Php fread的下载速度比readfile慢得多
我通过一个PHP脚本从URL向我的用户提供下载服务。使用Php fread的下载速度比readfile慢得多,php,download,fopen,readfile,Php,Download,Fopen,Readfile,我通过一个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: atta
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和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;
}
使用及
您还可以尝试将文件读取长度变大,并加入usleep()以降低执行速度。
无论如何,对于最新版本的PHP,流函数似乎比fread更受推荐。
您可能还希望在fread()或stream_get_contents()前面加一个@,以抑制任何错误,至少在生产中是这样。如果没有它,再加上一点小麻烦,你就会有一个损坏的文件。它可能在PHP或Apache中的某个地方进行缓冲(甚至可能是速率限制)。尝试更改:
while(!feof($file)) {
echo fread($file, 2014);
}
致:
(前缀@
是因为他们可能会抱怨缓冲区空。)
正如淡水先生所说,您应该对您的fread
呼叫进行错误检查,因此我在上面添加了一些基本内容。原因是2014年。操作系统获取4096字节数据的速度比其他操作系统快。但若你们写2014,那个么操作系统会尝试从文件中读取一个字节的数据来计算它。这就是为什么要花这么长时间。将2014更改为4096您真的需要输出缓冲吗?尝试ob_end_flush()代码>我不确定,我从其他地方得到了这段代码,它有输出缓冲。我应该把ob_end_flush()放在哪里代码>?在开始编写之前将其放在任何地方。如果增加fread的长度参数(示例中的2014),会发生什么情况?顺便问一下,文件的大小是多少?没什么,长度参数已经超过了相应的下载速度。文件大小约为100mb。这是一个猜测,还是应该更快一些?我希望看到一些替代方案的基准。这需要一些解释。如果stream\u get\u contents的速度更快,那么为什么fread不做stream\u get\u contents所做的事情呢?这是基于知道stream\u get\u contents()不会超时,并根据服务器的条件处理它所知道的事情。我只是用一个没有读取长度的大文件尝试了每种方法,fread超时导致了一个内部服务器错误,流的内容也正常工作。但在2014年的读取长度下,两者的平均执行时间大致相同。我希望我的评论能和其他人同步,但我并没有“添加评论”按钮。您的回复是第一次出现,但仅针对此块。这是问题的解决方案,但我最终使用了不同的方法使用cURL和CURLOPT_WRITEFUNCTION
,我将在帖子中编辑它。cURL允许我轻松地将HTTP范围头添加到请求中。谢谢!:)您还可以在启动stream_context_create()时添加HTTP读取器。查看文档。它应该以同样的方式工作。不管怎样,我只是想提一下。
while(!feof($file)) {
echo fread($file, 2014);
}
while(!feof($file)) {
$s=fread($file, 2014);
if($s===false)break; //Crude
echo $s;
@ob_flush();@flush();
}