PHP站点大文件下载频繁中断问题排查求助
PHP大文件下载频繁中断问题排查
我搭建了一个支持用户下载文件的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); }
目前文件可正常触发下载,但存在频繁中断问题:例如下载2GB文件时会中断30-50次,每次都需要手动点击浏览器菜单中的“继续”按钮恢复。请问该问题的可能根源是什么?
可能的问题根源及排查方向
1. PHP执行超时限制
PHP默认max_execution_time通常为30或60秒,下载2GB文件的时长远超这个阈值,PHP会主动终止脚本,导致连接中断。
解决方向:
- 在代码开头添加
set_time_limit(0);关闭脚本执行时间限制; - 或修改
php.ini中的max_execution_time参数,设置为更大值(如3600)。
2. 服务器连接超时配置
Apache或Nginx的默认连接超时设置不足以支撑大文件下载:
- Apache的
Timeout参数默认通常60秒,超时后服务器主动断开连接; - Nginx的
send_timeout、proxy_read_timeout(若用反向代理)也会限制连接时长。
解决方向:
- 调整服务器配置文件中的超时参数,例如将Apache的
Timeout设为3600,Nginx的send_timeout设为3600s。
3. 代码文件读取逻辑缺陷
当前代码每次循环固定减去1MB的$chunk长度,但fread实际返回的字节数可能小于$chunk(如文件剩余不足1MB时),会导致$length变为负数,后续循环异常提前终止输出。
解决方向:
修改循环内的读取逻辑,按实际读取字节数调整剩余长度:
$chunk = 1024 * 1024; while ($length > 0 && !feof($fd)) { $readSize = min($chunk, $length); $content = fread($fd, $readSize); if ($content === false) break; print $content; $length -= strlen($content); if (ob_get_level() > 0) ob_flush(); flush(); if (connection_status() != 0) { @fclose($fd); return; } }
4. 输出缓冲与压缩干扰
若服务器开启输出缓冲(output_buffering)或Gzip压缩(Apache的mod_deflate、Nginx的gzip),PHP输出内容会被服务器缓冲,无法及时发送到客户端,浏览器会判定连接超时并中断下载。
解决方向:
- 在代码开头添加
ini_set('output_buffering', '0');关闭PHP输出缓冲; - 添加响应头
header('Content-Encoding: none');禁用Gzip压缩,或在服务器配置中排除下载路径的压缩规则。
5. 网络层面不稳定
客户端网络链路丢包、中间路由超时等问题也会导致下载中断,但结合“需手动点击继续”的现象,服务端配置或代码问题的可能性更大。
内容的提问来源于stack exchange,提问作者Nickolas Etyuhibosecyu
相关产品推荐
相关产品推荐

