php实现边播边下载
实现边播边下载的基本原理
边播边下载(也称为流式下载或渐进式下载)的核心是将媒体文件分块传输,播放器可以逐块加载和播放,无需等待整个文件下载完成。PHP可通过控制HTTP响应头和数据分块传输实现这一功能。
设置正确的HTTP响应头
关键头部包括Accept-Ranges、Content-Length和Content-Range:

header("Accept-Ranges: bytes");
header("Content-Type: video/mp4"); // 根据实际格式调整
处理范围请求(Range Request)
客户端会发送Range头部请求特定字节范围,PHP需解析并返回对应数据块:
$filePath = 'path/to/video.mp4';
$fileSize = filesize($filePath);
$chunkSize = 1024 * 1024; // 1MB分块
if (isset($_SERVER['HTTP_RANGE'])) {
preg_match('/bytes=(\d+)-(\d+)?/', $_SERVER['HTTP_RANGE'], $matches);
$start = intval($matches[1]);
$end = $matches[2] ?? min($start + $chunkSize, $fileSize - 1);
header("Content-Length: " . ($end - $start + 1));
header("Content-Range: bytes $start-$end/$fileSize");
header("HTTP/1.1 206 Partial Content");
} else {
$start = 0;
$end = min($chunkSize, $fileSize - 1);
header("Content-Length: $fileSize");
}
分块读取并输出文件内容
使用fopen和fseek定位文件指针,逐块输出数据:

$handle = fopen($filePath, 'rb');
fseek($handle, $start);
$remaining = $end - $start + 1;
while (!feof($handle) && $remaining > 0) {
$chunk = min(8192, $remaining);
echo fread($handle, $chunk);
$remaining -= $chunk;
flush();
}
fclose($handle);
前端播放器配合
HTML5的<video>标签原生支持范围请求:
<video controls>
<source src="stream.php?file=video.mp4" type="video/mp4">
</video>
优化与注意事项
大文件处理建议使用内存映射或缓存机制避免内存耗尽。对于私有文件需添加身份验证逻辑。Nginx/Apache等服务器可直接处理静态文件的范围请求,动态生成场景才需PHP实现。
完整示例代码
$file = 'path/to/video.mp4';
if (file_exists($file)) {
$size = filesize($file);
$fp = fopen($file, 'rb');
header("Accept-Ranges: bytes");
header("Content-Type: video/mp4");
if (isset($_SERVER['HTTP_RANGE'])) {
$range = $_SERVER['HTTP_RANGE'];
list($start, $end) = sscanf($range, "bytes=%d-%d");
$end = min($end ?? $start + 1024*1024, $size-1);
header("HTTP/1.1 206 Partial Content");
header("Content-Length: " . ($end - $start + 1));
header("Content-Range: bytes $start-$end/$size");
fseek($fp, $start);
} else {
header("Content-Length: $size");
}
while (!feof($fp)) {
echo fread($fp, 8192);
flush();
}
fclose($fp);
}






