You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 07:10:02