【PHP 断点续传详解】
断点续传是一种网络传输技术,允许用户在中断下载后从上次停止的地方继续下载,极大地提高了大文件传输的效率和用户体验。在PHP中实现断点续传主要依赖于HTTP协议中的`Content-Range`报头。下面我们将详细讲解如何在PHP中实现这一功能。
理解`Content-Range`报头的含义至关重要。当服务器接收到客户端带有`HTTP_RANGE`的请求时,`Content-Range`报头用来告知客户端响应资源的范围。例如,如果客户端请求了文件的一部分,服务器会返回`Content-Range: bytes x-y/z`,其中x是开始位置,y是结束位置,z是文件总大小。这样,客户端就可以知道它已经下载了哪些部分,并在下次请求时仅获取缺失的部分。
以下是一个简单的PHP断点续传实例:
```php
$file = $_GET['video'];
$size = filesize($file);
$size2 = $size - 1;
$range = 0;
if (isset($_SERVER['HTTP_RANGE'])) {
header('HTTP /1.1 206 Partial Content');
$range = str_replace('=','-',$_SERVER['HTTP_RANGE']);
$range = explode('-', $range);
$range = trim($range[1]);
header('Content-Length:'.$size);
header('Content-Range: bytes '.$range.'-'.$size2.'/'.$size);
} else {
header('Content-Length:'.$size);
header('Content-Range: bytes 0-'.$size2.'/'.$size);
}
header("Content-type: video/mp4");
header('Accept-Ranges: bytes');
header('application/octet-stream');
header("Cache-control: public");
header("Pragma: public");
// 处理IE下载时的中文乱码问题
$ua = $_SERVER['HTTP_USER_AGENT'];
if (preg_match('/MSIE/', $ua)) {
$ie_filename = str_replace('+', '%20', urlencode($file));
header('Content-Disposition:attachment; filename='.$ie_filename);
} else {
header('Content-Disposition:attachment; filename='.$file);
}
$fp = fopen($file, 'rb+');
fseek($fp, $range);
while (!feof($fp)) {
set_time_limit(0); // 控制脚本运行时间
print(fread($fp, 1024)); // 读取文件并输出
ob_flush(); // 刷新PHP缓冲区
flush(); // 刷新Web服务器缓冲区
}
fclose($fp);
```
在这个例子中,我们首先检查`HTTP_RANGE`是否存在,然后根据范围设置响应头。接着,我们打开文件并定位到指定的范围,然后逐块读取文件并输出。`set_time_limit(0)`确保脚本不会因为超时而终止,这对于处理大文件是必要的。同时,`ob_flush()`和`flush()`确保数据实时发送到客户端,而不是等待缓冲区填满。
值得注意的是,`set_time_limit(0)`可能在某些环境中不起作用,尤其是安全模式开启或者限制了脚本执行时间的情况下。在这种情况下,可能需要在php.ini中禁用`safe_mode`或调整`max_execution_time`的值。另外,确保服务器支持并正确配置了`Accept-Ranges`,这样才能正确处理客户端的断点续传请求。
总结起来,PHP实现断点续传的关键在于正确设置HTTP响应头和处理文件读取。通过理解`Content-Range`报头的工作机制,我们可以有效地优化大文件下载,提供更好的用户体验。同时,注意与服务器配置、浏览器兼容性以及PHP环境相关的因素,确保断点续传功能的稳定运行。