我有一个 PHP 网站,用户可以在上面下载文件。 这是代码:
if (isset($_SERVER['HTTP_RANGE']))
{
$partialContent = true;
preg_match('/bytes=(\d+)-(\d+)?/', $_SERVER['HTTP_RANGE'], $matches);
$offset = intval($matches[1]);
$length = (isset($matches[2]) ? intval($matches[2]) : $filesize) - $offset;
}
else
$partialContent = false;
if (ob_get_level())
ob_end_clean();
header('Pragma: public');
header('Expires: -1');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Content-Disposition: attachment; filename="'.basename($file).'"');
header('Content-Type: application/octet-stream');
if ($partialContent)
{
header('HTTP/1.1 206 Partial Content');
header('Content-Range: bytes '.$offset.'-'.($offset + $length - 1).'/'.$filesize);
}
header('Content-Length: '.$length);
header('Accept-Ranges: bytes');
if ($fd = fopen($file, 'rb'))
{
fseek($fd, $offset);
$chunk = 1024 * 1024;
while (!feof($fd))
{
print fread($fd, $chunk);
$length -= $chunk;
if (ob_get_level() > 0)
ob_flush();
flush();
if (connection_status() != 0)
{
@fclose($fd);
return;
}
}
fclose($fd);
}
文件正在下载,但问题是下载被中断很多次(例如,在我的计算机上,2 GB 文件 - ~30-50 次,但它是一个浮动值),并且每次都需要按浏览器菜单中的“恢复”。这个问题的根源在哪里?
感谢@KIKOSoftware,问题现已得到解决。需要使用
set_time_limit()
。这是代码的工作版本:
if (isset($_SERVER['HTTP_RANGE']))
{
$partialContent = true;
preg_match('/bytes=(\d+)-(\d+)?/', $_SERVER['HTTP_RANGE'], $matches);
$offset = intval($matches[1]);
$length = (isset($matches[2]) ? intval($matches[2]) : $filesize) - $offset;
}
else
$partialContent = false;
if (ob_get_level())
ob_end_clean();
header('Pragma: public');
header('Expires: -1');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Content-Disposition: attachment; filename="'.basename($file).'"');
header('Content-Type: application/octet-stream');
if ($partialContent)
{
header('HTTP/1.1 206 Partial Content');
header('Content-Range: bytes '.$offset.'-'.($offset + $length - 1).'/'.$filesize);
}
header('Content-Length: '.$length);
header('Accept-Ranges: bytes');
if ($fd = fopen($file, 'rb'))
{
fseek($fd, $offset);
$chunk = 1024 * 1024;
while (!feof($fd))
{
set_time_limit(60);
print fread($fd, $chunk);
$length -= $chunk;
if (ob_get_level() > 0)
ob_flush();
flush();
if (connection_status() != 0)
{
@fclose($fd);
return;
}
}
fclose($fd);
}