登录
首页 >  文章 >  php教程

PHP获取远程文件大小方法解析

时间:2026-04-01 16:08:29 320浏览 收藏

PHP中通过get_headers获取远程文件大小极不可靠,因其易受重定向、分块传输、动态脚本输出及CDN缓存干扰而导致Content-Length为空或错误;更稳健的方案是使用cURL手动控制HEAD请求——禁用自动跳转、设置超时、校验响应码,并优先从CURLINFO_CONTENT_LENGTH_DOWNLOAD提取尺寸;若失败,则退化为带Range: bytes=0-0的GET请求,解析Content-Range头获取总大小,同时结合Accept-Ranges支持判断与响应状态码(206优先采信,200需谨慎处理),最终实现对各类远程资源(静态文件、PHP下载脚本、CDN托管内容)的自适应、高兼容性大小探测。

PHP怎么获取远程文件大小_get_headers获取Content-Length【说明】

get_headers 在 PHP 中确实能拿到 Content-Length,但**绝大多数情况下它不靠谱——尤其是对重定向、分块传输、动态脚本或 CDN 缓存后的响应**。

为什么 get_headers 返回的 Content-Length 经常是空或错的

HTTP 协议本身不要求服务器返回 Content-Length;现代服务更倾向用 Transfer-Encoding: chunked 或直接省略该头。PHP 的 get_headers 默认只发 HEAD 请求,而很多 Web 服务器(比如 Nginx + PHP-FPM)对 HEAD 的处理会丢掉 Content-Length,哪怕 GET 能拿到。

  • 遇到 301/302 重定向时,get_headers 默认跟随,但中间跳转响应可能没 Content-Length,最终返回的是最后一跳的头——而那一跳可能是空响应体或网关页
  • PHP 脚本(如 download.php?id=123)通常用 readfile()fopen() + stream_copy_to_stream() 输出,压根不设 Content-Length
  • CDN 或反向代理(如 Cloudflare)可能剥离或伪造原始头,Content-Length 变成不可信值

真要获取远程文件大小,得换方法:用 curlHEAD 并手动控制行为

get_headers 更可控,关键是显式关闭重定向、设置超时、检查真实响应码,并允许 fallback 到 GET(带 Range 头只取首字节)。

  • 先用 curl_setopt($ch, CURLOPT_NOBODY, true)HEAD,同时设 CURLOPT_FOLLOWLOCATIONfalse
  • 检查 curl_getinfo($ch, CURLINFO_HTTP_CODE) 是否为 200;若为 3xx,需手动解析 Location 头再试一次(不能依赖自动跳转)
  • curl_getinfo($ch, CURLINFO_CONTENT_LENGTH_DOWNLOAD) 读大小——这个值是 cURL 内部解析响应头后提取的,比自己 array_search 更稳
  • 如果该值为 -1 或空,说明头里没给,可退化为 GET + Range: bytes=0-0,然后看 Content-Range 头里的总长度(如 bytes 0-0/1234567

示例关键逻辑:

$ch = curl_init('https://example.com/file.zip');
curl_setopt($ch, CURLOPT_NOBODY, true);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_exec($ch);
$size = curl_getinfo($ch, CURLINFO_CONTENT_LENGTH_DOWNLOAD);
curl_close($ch);

别忽略 Content-RangeAccept-Ranges 这两个“备胎”头

有些服务(特别是静态文件托管或支持断点续传的 API)虽然不返回 Content-Length,但会返回 Accept-Ranges: bytes,配合一次带 Range: bytes=0-0GET 请求,就能从 Content-Range 响应头里拿到完整尺寸。

  • Content-Range: bytes 0-0/8388608 → 总大小就是 8388608
  • 若响应码是 206 Partial Content,说明服务支持分片,Content-Range 可信;若是 200,那这个 Range 请求被无视了,不能采信
  • 注意:某些 CDN(如阿里云 OSS)对小文件会合并响应,Range 请求可能直接返回完整内容且状态码为 200,此时需靠 Content-LengthContent-Range 是否存在来判断

真正难的不是写几行代码,而是得根据目标 URL 的实际响应特征动态选策略:先 HEAD,失败就 Range,再失败才考虑下载整个头(不推荐)。没人能保证一个函数调用就搞定所有远程地址。

理论要掌握,实操不能落!以上关于《PHP获取远程文件大小方法解析》的详细介绍,大家都掌握了吧!如果想要继续提升自己的能力,那么就来关注golang学习网公众号吧!

资料下载
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>