通过解析HTTP Range头实现分段下载,设置206状态码及Content-Range响应头,结合fopen、fread流式输出文件内容,支持断点续传。

PHP 8.4 本身不内置断点续传下载功能,但完全可以通过标准 HTTP 协议 + 原生函数 + 正确响应头实现可靠的断点续传下载。关键不在版本新旧,而在是否正确解析 Range 请求、返回 206 Partial Content、设置 Content-Range 和流式输出文件。
基础下载:强制触发浏览器保存而非打开
先确保文件不被浏览器直接渲染(如 PDF、图片、JSON),而是弹出下载框:
- 用
Content-Disposition: attachment明确声明为附件 - 设
Content-Type: application/octet-stream避免 MIME 类型猜测 - 调用
ob_clean()和flush()清除前置输出干扰 - 用
fopen() + fread() + fpassthru()或分块readfile()流式输出,避免内存爆满
断点续传核心:识别 Range 并精准返回片段
客户端(如下载器、curl、浏览器)恢复下载时会发带 Range: bytes=1024-2047 的请求。PHP 需解析并响应:
- 检查
$_SERVER['HTTP_RANGE']是否存在且格式合法(正则匹配bytes=(\d+)-(\d*)) - 计算起始字节
$start(默认 0)、结束字节$end(默认文件末尾 -1) - 发送状态码
http_response_code(206) - 设置
Content-Range: bytes $start-$end/$file_size和Content-Length: $end - $start + 1 - 用
fseek($fp, $start)定位文件指针,再逐块读取输出
安全与健壮性必须项
生产环境不能只管功能,还要防滥用和崩溃:
- 文件路径必须校验:禁止
../路径遍历,建议将可下载文件统一放在 Web 根目录外(如/var/data/downloads/) - 文件存在性、可读性、权限需双重判断:
is_file()+is_readable() - 文件名过滤:用
basename()提取,禁用空格、控制字符、特殊符号;必要时重命名(如加哈希前缀) - 超大文件设
set_time_limit(0),但配合ignore_user_abort(true)防止用户关闭页面中断传输 - 推荐使用固定缓冲区(如 8192 字节),每次
fread()后ob_flush()+flush()确保实时推送
PHP 8.4 可用的完整示例(无依赖、单文件)
以下代码已适配 PHP 8.4 语法(如严格类型提示可选,str_starts_with() 等新函数可用,但此处保持兼容性):
<?php function downloadFile(string $filePath): void {
if (!is_file($filePath) || !is_readable($filePath)) {
http_response_code(404);
die('File not found or inaccessible.');
}
<pre class="brush:php;toolbar:false;">$fileName = basename($filePath);
$fileSize = (int) filesize($filePath);
// 检查 Range 请求
$range = $_SERVER['HTTP_RANGE'] ?? null;
$start = $end = null;
if ($range && preg_match('/^bytes=(\d+)-(\d*)$/', $range, $matches)) {
$start = (int) $matches[1];
$end = isset($matches[2]) && $matches[2] !== '' ? (int) $matches[2] : $fileSize - 1;
if ($end >= $fileSize) $end = $fileSize - 1;
if ($start > $end || $start <p>}</p><p>// 使用示例(配合路由或参数验证)
// $safePath = '/var/data/uploads/' . filter_var($_GET['id'], FILTER_SANITIZE_STRING);
// downloadFile($safePath);
?></p>
不复杂但容易忽略:断点续传不是“高级功能”,而是 HTTP 协议原生能力。PHP 8.4 只需按规范响应,所有主流下载工具(IDM、Chrome、wget、curl)都能自动识别并复用 Range。真正影响体验的是服务端是否稳定流式输出、是否做足路径与权限校验。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











