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
相关产品推荐
相关产品推荐

