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

PHP脚本仅下载部分图片问题求助:旧服务器正常新服务器异常

这问题我之前帮朋友排查过类似的,大概率是新服务器的输出缓冲、连接超时或者传输限制搞的鬼,咱们一步步来理:

问题核心分析

你遇到的情况是:PHP图片下载脚本在旧服务器能完整下载图片,但迁移到新服务器后,下载停滞在1,083 KB / 1,382 KB后中断,图片底部缺失,调整PHP配置和版本也没解决。这种情况通常和服务器端的输出缓冲、连接超时、传输限制或者脚本本身的输出控制逻辑有关,和PHP版本的直接关联不大。

排查与解决方案

1. 强制关闭输出缓冲并完善响应头

新服务器可能默认开启了输出缓冲,导致数据无法实时推送给客户端,中断后只输出了缓冲内的部分内容。同时一定要给客户端返回准确的文件大小,不然客户端无法判断下载是否完成。修改脚本如下:

<?php
$file = "test-download-image.jpg";
if (file_exists($file)) {
    // 清空并关闭所有输出缓冲
    ob_end_clean();
    // 开启隐式刷新,每输出一点内容就推送给客户端
    ob_implicit_flush(true);
    
    $filesize = filesize($file);
    // 完善响应头,关键是Content-Length必须准确
    header("Pragma: public");
    header("Expires: 0");
    header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
    header("Content-Type: image/jpeg");
    header("Content-Length: " . $filesize);
    header("Content-Disposition: attachment; filename=\"" . basename($file) . "\"");
    
    // 读取文件并输出
    readfile($file);
    exit;
}
?>

2. 检查服务器的连接超时设置

新服务器的Apache/Nginx或PHP-FPM的超时时间可能比旧服务器短,导致大文件还没传输完成就被强制断开:

  • Apache:打开httpd.conf,找到Timeout参数,调至60以上(比如Timeout 120),保存后重启服务
  • Nginx:修改nginx.conf,调整proxy_connect_timeout、proxy_send_timeout、proxy_read_timeout,以及fastcgi_connect_timeout、fastcgi_send_timeout、fastcgi_read_timeout,统一设置为60s以上,重启Nginx
  • PHP-FPM:编辑php-fpm.conf,修改request_terminate_timeout参数,确保时间足够覆盖文件传输所需时长,重启PHP-FPM

3. 禁用针对图片的服务器压缩

有些新服务器默认开启了Gzip/Brotli压缩,但图片本身已经是压缩格式,二次压缩可能导致传输异常:

  • Apache:在网站根目录的.htaccess里添加:
    SetEnvIfNoCase Request_URI \.(jpg|jpeg)$ no-gzip dont-vary
    
  • Nginx:在站点配置的location块里添加:
    location ~* \.(jpg|jpeg)$ {
        gzip off;
    }
    

4. 改用分段传输(支持断点续传)

如果以上方法都无效,可能是客户端或中间网络的限制导致,支持Range请求可以让客户端断点续传,也能避免一次性传输大文件的压力:

<?php
$file = "test-download-image.jpg";
if (file_exists($file)) {
    $filesize = filesize($file);
    $offset = 0;
    $length = $filesize;

    // 处理客户端的Range请求
    if (isset($_SERVER['HTTP_RANGE'])) {
        preg_match('/bytes=(\d+)-(\d+)?/', $_SERVER['HTTP_RANGE'], $matches);
        $offset = intval($matches[1]);
        $length = $matches[2] ? intval($matches[2]) - $offset + 1 : $filesize - $offset;
        header("HTTP/1.1 206 Partial Content");
        header("Content-Range: bytes $offset-" . ($offset + $length - 1) . "/$filesize");
    }

    ob_end_clean();
    ob_implicit_flush(true);
    header("Pragma: public");
    header("Expires: 0");
    header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
    header("Content-Type: image/jpeg");
    header("Content-Length: $length");
    header("Content-Disposition: attachment; filename=\"" . basename($file) . "\"");

    // 分块读取并输出文件
    $fp = fopen($file, 'rb');
    fseek($fp, $offset);
    while ($length > 0) {
        $chunk = min(1024 * 1024, $length); // 每次读取1MB
        echo fread($fp, $chunk);
        $length -= $chunk;
        flush(); // 强制推送输出
    }
    fclose($fp);
    exit;
}
?>
额外排查建议
  • 先测试直接访问图片文件(不用PHP脚本)能不能完整下载,如果直接访问也中断,那就是服务器静态文件传输的问题,和PHP无关,重点排查Nginx/Apache的配置
  • 检查新服务器的磁盘IO和网络带宽,有时候磁盘性能差、带宽受限也会导致传输中断

内容的提问来源于stack exchange,提问作者user3079103

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 03:37:51