filesize() 返回原始字节数,使用前须用file_exists()和is_readable()校验文件状态,大文件需注意32位系统整型溢出,刚写入文件需clearstatcache()刷新缓存,远程url不支持直接调用。

filesize() 返回的是原始字节数,直接用它读文件内容或判断上传大小时,不加防护容易出错——比如缓存导致读旧值、大文件溢出、远程文件直接失败。
调用前必须检查文件是否存在和可读
filesize() 不会自动帮你确认文件状态,传入不存在或权限不足的路径,它就返回 false 并触发 E_WARNING,而不是抛异常。线上环境可能因此暴露路径或中断流程。
- 永远先用
file_exists()判断路径有效性 - 再用
is_readable()确认 PHP 进程有读权限(尤其在容器或 SELinux 环境下) - 不要只靠
if (filesize($f))做判断——因为 0 字节文件也合法,但filesize()返回0,不是false
正确写法示例:
$file = '/var/uploads/photo.jpg';
if (file_exists($file) && is_readable($file)) {
$size = filesize($file);
if ($size !== false) {
echo "大小:{$size} 字节";
}
}
大文件(>2GB)在 32 位系统上会返回负数或截断
PHP 默认用有符号 32 位整数表示大小,超过 231−1 字节(≈2.15GB)后,filesize() 可能返回负值或错误值,比如 -1234567890。
- 64 位系统 PHP(推荐)天然支持大文件,无需额外处理
- 若必须兼容 32 位环境,对 2–4GB 文件可用
sprintf("%u", filesize($file))强制无符号输出 - 超过 4GB 的文件,
filesize()无法可靠表示,应改用fstat(fopen($file, 'rb'))['size'](仍受 PHP 整型限制),或换用外部命令如stat -c "%s" $file
刚写入的文件立即读 size 会不准
常见于日志追加、临时文件生成后立刻调用 filesize(),结果还是旧大小——这是 PHP 的 stat 缓存机制导致的,不是磁盘延迟。
- Linux/macOS 下,内核级 stat 结果被 PHP 用户态缓存,多次调用
filesize()会复用上次结果 - 解决方法:在
filesize()前加clearstatcache(true, $filename),第二个参数指定具体文件,避免全局清缓存影响性能 - 注意:
clearstatcache()本身不解决 NFS 或网络文件系统的一致性问题,这类场景建议用touch+ 时间戳校验替代 size 判断
典型踩坑代码:
$fp = fopen('log.txt', 'a');
fwrite($fp, "new line\n");
fclose($fp);
// 此时 filesize() 很可能仍是旧值
$size = filesize('log.txt'); // ❌
// 正确做法:
clearstatcache(true, 'log.txt');
$size = filesize('log.txt'); // ✅
远程 URL 不能直接用 filesize(),除非 wrapper 显式支持
虽然文档说 “自 PHP 5.0.0 起支持某些 URL wrapper”,但实际只有极少数(如 file://、部分 ftp://)实现了 stat() 功能;http:// 和 https:// 完全不支持,强行调用会警告并返回 false。
- 想获取 HTTP 文件大小,必须发 HEAD 请求读
Content-Length头(注意:服务器未必返回,分块传输或动态生成内容时该头可能缺失) - 用
curl更可靠:curl_setopt($ch, CURLOPT_NOBODY, true)+curl_getinfo($ch, CURLINFO_CONTENT_LENGTH_DOWNLOAD) - 别依赖
filesize('https://...')—— 它在绝大多数生产环境中就是个摆设
真正麻烦的从来不是函数怎么写,而是你没意识到它背后连着操作系统缓存、整型边界、权限模型和协议限制——这些点漏掉一个,线上就可能卡住上传、读错日志或误判文件完整性。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











