php无法直接限制文件夹大小,需通过递归统计目录大小并在写入前校验,配合flock避免并发超限,系统级限制须依赖linux quota或独立分区。

PHP 本身无法直接限制文件夹大小
PHP 是脚本语言,不提供类似操作系统级的磁盘配额(quota)功能,也没有内置函数如 set_folder_size_limit() 这种东西。所谓“限制文件夹大小”,本质是靠 PHP 主动检查 + 拒绝写入来模拟,不是真正的系统级硬限制。
这意味着:你必须在每次上传、写入、追加前手动计算当前目录总大小,并判断是否超限——漏掉一次检查,就可能突破上限。
用 recursiveDirectorySize() 统计文件夹真实大小
PHP 没有现成的 disk_total_space() 对应目录版,得自己递归遍历。注意别用 scandir() 简单叠加,会漏掉子目录或跳过权限不足的路径。
- 推荐用
RecursiveIteratorIterator+RecursiveDirectoryIterator,能自动处理符号链接和权限异常 - 务必用
try/catch包裹迭代过程,避免因某个子目录不可读导致整个统计失败 - 对大目录要加执行时间限制(
set_time_limit(5)),否则可能超时
示例关键逻辑:
立即学习“PHP免费学习笔记(深入)”;
function recursiveDirectorySize($path) {
$size = 0;
$iterator = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS),
RecursiveIteratorIterator::LEAVES_ONLY
);
foreach ($iterator as $file) {
if ($file->isFile()) {
try { $size += $file->getSize(); } catch (Exception $e) { continue; }
}
}
return $size;
}
上传前校验 + 拒绝写入的典型流程
这是最常用也最易出错的一环。很多人只在校验时算一次大小,却忽略并发写入竞争条件(两个请求同时通过校验,然后一起写入超限)。
- 校验必须紧贴实际写入操作,中间不能有其他耗时逻辑
- 建议用
flock()对一个临时锁文件加写锁,确保同一时间只有一个进程在判断+写入 - 阈值建议预留缓冲(比如设 100MB 上限,实际在 95MB 就拒绝),避免刚校验完就有其他进程写入几 KB 导致超限
- 返回错误时明确提示剩余空间,而不是只抛
"Folder full",方便前端反馈
Linux 系统层才是真限制,PHP 只能配合
如果真要强约束,必须落到系统层:给 Web 服务运行用户(如 www-data)配置磁盘配额(quota),或把上传目录挂载为独立分区并设 size= 选项(如 tmpfs)。PHP 此时只需捕获 mkdir(): Disk quota exceeded 或 file_put_contents(): No space left on device 这类系统级错误并友好提示。
注意:disk_free_space() 返回的是整个文件系统空闲空间,不是目录配额余量——它在 quota 启用后依然显示物理磁盘剩余,不能替代配额查询。
真正麻烦的是跨服务器部署场景:PHP 层模拟限制容易,但系统配额需要运维介入,且不同环境(Docker、共享主机、云盘)支持程度差异极大。多数项目最终妥协为“PHP 校验 + 定期巡检脚本清理”。











