phpEnv与Nginx断点续传完全无关,后者依赖Nginx的range模块、Range头透传及PHP手动响应206状态码,三者缺一不可。

phpEnv 本身不参与 Nginx 的断点续传配置,它只管理 PHP 多版本环境;Nginx 的 Range 支持与 phpEnv 完全无关,强行混用会导致配置错位、调试困难。
phpEnv 和 Nginx 断点续传是两套独立系统
phpEnv 负责切换 php 可执行文件和 php.ini,它不修改 Nginx 配置、不代理请求、不处理 HTTP 头。你用 phpEnv 切到 PHP 8.2,和 Nginx 能不能返回 206 Partial Content 没有任何因果关系。
常见误解场景:
- 以为 “装了 phpEnv 就能开断点续传”,结果 Nginx 还卡在默认静态服务模式,
Range请求直接被忽略 - 在
~/.phpenv/versions/8.2.0/etc/php.ini里调大upload_max_filesize,却忘了 Nginx 的client_max_body_size仍是 1M,上传直接 413 - 用 phpEnv 启的内置服务器(
php -S)跑上传接口,但该服务器根本不支持Range,也无法透传头给后端
Nginx 静态文件下载必须显式启用 range 支持
即使你用 phpEnv 管理 PHP 版本,只要 Nginx 直接 serve 文件(比如 location /downloads { alias /data/files/; }),就必须确认:ngx_http_range_module 已编译进 Nginx(默认包含),且未被禁用。
立即学习“PHP免费学习笔记(深入)”;
检查方式(无需重启):
- 运行
nginx -V 2>&1 | grep -o with-http-range-module,有输出即表示模块存在 - 确保 location 块中没写
range off;—— 这个指令会彻底关闭 range 功能 - 用
curl -I -H "Range: bytes=0-1023" https://yoursite.com/big.zip测试:成功时返回HTTP/2 206和Content-Range;失败则返回200或416
PHP 动态下载接口必须手动解析 Range 并控制输出
如果你的下载走的是 PHP 脚本(如 /download.php?file=xxx),那 Nginx 的 range 模块完全不生效——所有逻辑得由 PHP 自己实现。这时 phpEnv 只影响 PHP 版本兼容性,不解决核心问题。
关键操作点:
- 必须读取
$_SERVER['HTTP_RANGE'],不能依赖getallheaders()(CLI 或某些 SAPI 下不可用) - 用
fopen($file, 'rb')+fseek()定位起始偏移,再fread()输出对应字节段 - 必须返回准确的
Content-Range、Content-Length和Accept-Ranges: bytes头,缺一不可 - 状态码必须是
206,不是200;否则浏览器认为是完整响应,不会触发续传
CDN 回源场景下,Nginx 必须透传 Range 头给 PHP 后端
当 CDN 在前、Nginx 作源站、PHP 处理下载逻辑时,Nginx 默认不会把 Range 和 If-Range 头转发给 fastcgi_pass 或 proxy_pass 的下游。这是最常被忽略的断点失效原因。
修复配置(加在 location ~ \.php$ 或对应 proxy 块内):
fastcgi_set_header Range $http_range; fastcgi_set_header If-Range $http_if_range; # 或 proxy_set_header Range $http_range; proxy_set_header If-Range $http_if_range;
漏掉这一条,PHP 收不到 Range,只能返回整个文件,CDN 缓存后所有后续请求都降级为全量传输。
真正容易出问题的地方不在 phpEnv,而在 Nginx 是否把 Range 头送到了 PHP 手里、PHP 是否按规范返回了 206、CDN 是否把 206 当作可缓存响应——这三个环节任意一个断裂,断点续传就形同虚设。



















