filesize()返回字节数,直接除1024不准确,因二进制(kib=1024)与十进制(kb=1000)混淆;应统一用kib/mib等iec单位,展示时明确标注,存储一律用整型字节值。

PHP里filesize()返回的是字节,直接除1024不准确
PHP的filesize()函数返回整型字节数,但“KB = 1024 字节”只是二进制换算习惯;实际存储设备厂商用的是十进制(1 KB = 1000 字节),而操作系统、PHP本身默认按二进制处理。所以简单写$size / 1024得到的KB值,在跨平台展示或与磁盘工具对比时容易对不上。
更关键的是:浮点精度和舍入方式会影响最终显示——比如1024 * 1024 - 1字节(即1MB差1字节),用round($size / 1024 / 1024, 2)会显示1.00,但其实是0.999999,四舍五入掩盖了真实量级。
- 统一用二进制单位(KiB、MiB、GiB)更符合PHP和Linux行为,推荐在内部计算和日志中使用
- 面向用户展示时,可选十进制(KB/MB/GB),但必须明确标注,避免混淆
- 永远不要用
intval()或(int)截断,会导致1023字节变成0 KB
用number_format() + 循环缩放比手动写if更稳
硬写一堆if ($size > 1073741824) { ... }不仅难维护,还容易漏掉边界(比如0字节、负数、false返回值)。PHP没有内置的“智能单位转换”函数,但可以用一个带单位数组的小循环完成所有情况。
示例逻辑:
立即学习“PHP免费学习笔记(深入)”;
function formatBytes($bytes, $decimals = 2) {
$units = ['B', 'KiB', 'MiB', 'GiB', 'TiB'];
$i = 0;
$bytes = (float)$bytes;
while ($bytes >= 1024.0 && $i < count($units) - 1) {
$bytes /= 1024.0;
$i++;
}
return number_format($bytes, $decimals, '.', '') . ' ' . $units[$i];
}-
$bytes强制转float,防止大整数溢出后变成0或科学计数法字符串 - 用
while而非for,避免单位数组越界,也兼容未来加PiB -
number_format()第三个参数必须是'.',否则在某些locale下会输出逗号小数点 - 别忘了检查
filesize()失败返回false,要先is_numeric()过滤
遇到filesize(): stat failed错误,别急着转单位
这个错误意味着文件根本读不到——路径不存在、权限不足、符号链接断裂,或者文件被另一个进程锁住。这时候再怎么优化单位换算都没意义。
- 先用
file_exists()和is_readable()双检,比直接调filesize()安全 - Windows下注意路径分隔符,
realpath()能帮你标准化,但会触发IO,高频调用需缓存 - 如果文件可能被并发写入(如日志),
filesize()可能返回不一致结果,建议加clearstatcache(true, $path)再查 - 超大文件(>2GB)在32位PHP中可能返回负数,要用
bcdiv()或gmp扩展处理,普通int会溢出
单位后缀大小写敏感:KiB ≠ KB
国际标准IEC 60027-2规定:二进制单位必须用KiB(kibi)、MiB(mebi),而KB、MB属于十进制单位。PHP社区普遍用KiB系,Linux ls -lh也显示KiB,但很多前端UI仍写KB。
- 如果你的API要对接监控系统(如Prometheus),它认
bytes原始值,单位全靠label,这时候别自己加后缀 - 数据库存大小,一律存
INT UNSIGNED字节值,别存带单位的字符串——排序、范围查询全崩 - 中文场景下,“KB”常被理解为“千字节”,用户其实不区分二进制/十进制,但技术文档、日志、调试输出请坚持用
KiB
单位换算是个看似简单、实则处处要对齐上下文的事:PHP内部、OS行为、硬件标称、用户认知、前后端约定——少对上一环,数字就对不上。最稳妥的做法是:存字节、算字节、只在最终展示层做一次带上下文的格式化。











