PHP 8.2中filesize()无法读取子目录文件大小的问题
问题分析与解决方案
核心原因
PHP文件系统函数(filesize()/file_exists()/is_readable())和浏览器<img>标签的访问逻辑完全不同:
- PHP函数是直接通过服务器本地文件系统访问,受PHP配置、系统安全策略双重限制;
<img>标签是通过Web服务器(Nginx/Apache等)的HTTP请求转发,只受Web服务器的目录权限和路由配置控制。
所以即使Web服务器能正常返回图片,PHP进程可能因为权限或配置限制无法直接读取文件。
排查与解决步骤
1. 检查open_basedir限制
这是最常见的原因,PHP的open_basedir配置会限制脚本能访问的本地目录范围:
- 执行
phpinfo()查看当前open_basedir的值,确认目标目录(比如/home/kingkong/media)是否在允许列表内; - 修改
php.ini(或对应站点的PHP配置文件),将目标目录添加到open_basedir:open_basedir = /home/kingkong:/tmp:/home/kingkong/media - 重启Web服务器和PHP-FPM(如果使用)生效。
2. 排查Linux安全模块(SELinux/AppArmor)
Linux发行版默认启用的SELinux或AppArmor可能会阻止PHP进程访问特定目录,即使文件权限设为777:
- 临时测试:执行
setenforce 0关闭SELinux,重新运行PHP脚本,如果问题解决,说明是SELinux策略导致; - 永久修复:给目标目录设置正确的Web内容上下文:
(Apache环境用chcon -R -t httpd_sys_content_t /home/kingkong/mediahttpd_sys_content_t,Nginx部分系统需改用nginx_sys_content_t,根据实际环境调整)
3. 检查符号链接问题
如果/media是符号链接(软链接):
- 执行
ls -l /home/kingkong/media查看链接指向的实际路径; - 确保链接的目标目录也在
open_basedir允许范围内,且PHP进程对目标目录有访问权限。
4. 打印详细错误信息定位
添加代码获取具体错误,帮助精准排查:
$filename = $_SERVER['DOCUMENT_ROOT'].'/media/photo.jpg'; echo $filename . '<br>'; $size = @filesize($filename); if ($size === false) { $error = error_get_last(); echo '详细错误:' . $error['message'] . '<br>'; } else { echo $size . ' bytes<br>'; }
内容的提问来源于stack exchange,提问作者karadayi
相关产品推荐
相关产品推荐

