Mac 11.6.6下PHP8.1 move_uploaded_file报权限拒绝错误排查
问题背景
运行环境信息:
- 操作系统:Mac 11.6.6
- PHP版本:8.1
- 问题场景:通过JavaScript异步向PHP站点上传文件时,
move_uploaded_file函数执行失败,抛出权限拒绝警告。
相关代码
PHP上传处理逻辑
ini_set ('error_reporting', E_ALL); ini_set ('display_errors', 1); ini_set ('display_startup_errors', 1); echo 'username = ' . `whoami`."\n"; var_dump($_FILES); $str_name = $_FILES['file']['name']; echo '$str_name = '.$str_name."\n"; $str_tmp = $_FILES['file']['tmp_name']; echo '$str_tmp = '.$str_tmp."\n"; $str_tmpdir = substr($_FILES['file']['tmp_name'], 0, strrpos($_FILES['file']['tmp_name'], '/')); echo '$str_tmpdir = '.$str_tmpdir."\n\n"; echo 'is_dir($str_tmpdir) = '.(is_dir($str_tmpdir) ? 'true' : 'false')."\n\n"; echo 'is_writable($str_tmp) = '.(is_writable($str_tmp) ? 'true' : 'false')."\n\n"; echo 'ini_get("file_uploads") = '.ini_get('file_uploads')."\n\n"; $location = "/Library/WebServer/Documents/pjamesnorris/img/".$str_name; echo "\n".'move_uploaded_file("'.$_FILES['file']['tmp_name'].'", "'.$location.'")) = '.(move_uploaded_file($_FILES['file']['tmp_name'], $location) ? 'Success' : 'Failure');
前端JS上传代码
async function uploadFile() { let formData = new FormData(); formData.append("file", fileupload.files[0]); await fetch('../php/upload.php', { method: "POST", body: formData }); alert('The file has been uploaded successfully.'); }
执行报错输出
username = _www array(1) { ["file"]=> array(6) { ["name"]=> string(17) "DantesInferno.jpg" ["full_path"]=> string(17) "DantesInferno.jpg" ["type"]=> string(10) "image/jpeg" ["tmp_name"]=> string(67) "/Library/WebServer/Documents/pjamesnorris/tmp_file_upload/phpRDWjOh" ["error"]=> int(0) ["size"]=> int(217602) } } $str_name = DantesInferno.jpg $str_tmp = /Library/WebServer/Documents/pjamesnorris/tmp_file_upload/phpRDWjOh $str_tmpdir = /Library/WebServer/Documents/pjamesnorris/tmp_file_upload is_dir($str_tmpdir) = true is_writable($str_tmp) = true ini_get("file_uploads") = 1 <br /> <b>Warning</b>: move_uploaded_file(/Library/WebServer/Documents/pjamesnorris/img/DantesInferno.jpg): Failed to open stream: Permission denied in <b>/Library/WebServer/Documents/pjamesnorris/php/upload.php</b> on line <b>28</b><br /> <br /> <b>Warning</b>: move_uploaded_file(): Unable to move "/Library/WebServer/Documents/pjamesnorris/tmp_file_upload/phpRDWjOh" to "/Library/WebServer/Documents/pjamesnorris/img/DantesInferno.jpg" in <b>/Library/WebServer/Documents/pjamesnorris/php/upload.php</b> on line <b>28</b><br /> move_uploaded_file("/Library/WebServer/Documents/pjamesnorris/tmp_file_upload/phpRDWjOh", "/Library/WebServer/Documents/pjamesnorris/img/DantesInferno.jpg")) = Failure
已排查确认项
- 临时上传目录
/Library/WebServer/Documents/pjamesnorris/tmp_file_upload存在,属主为_www,权限为drwxrwxr-x - 上传生成的临时文件可写
- PHP配置
file_uploads为开启状态 - 尝试将目标目录权限设为0777未解决问题,且该方案存在明确安全风险
排查思路与解决方案
Mac环境下这类设置权限后依然报权限拒绝的问题,高频诱因是系统隔离属性、目录属主不匹配、PHP访问路径限制,按以下顺序排查即可:
- 修正目标目录属主与基础权限
执行命令查看目标img目录的属性:
正常权限应为ls -ld /Library/WebServer/Documents/pjamesnorris/img/drwxr-xr-x(即755),属主为_www,如果不符合要求,执行以下命令修正:sudo chown -R _www:_www /Library/WebServer/Documents/pjamesnorris/img/ sudo chmod -R 755 /Library/WebServer/Documents/pjamesnorris/img/ - 清除macOS目录隔离属性
macOS会给下载、同步生成的目录自动添加com.apple.quarantine隔离属性,该属性优先级高于普通unix权限,即便是设置777权限也会阻止Web进程写入,这也是你设置0777依然失败的最常见原因。执行命令查看目录扩展属性:
如果输出中存在ls -l@ /Library/WebServer/Documents/pjamesnorris/img/com.apple.quarantine字段,执行命令递归删除整个站点目录的隔离属性:sudo xattr -r -d com.apple.quarantine /Library/WebServer/Documents/pjamesnorris/ - 校验Apache目录访问规则
打开Apache默认配置文件/etc/apache2/httpd.conf,找到/Library/WebServer/Documents/对应的Directory配置段,确认配置中已开启Require all granted,不存在针对_www用户的写入拒绝规则,修改完成后重启Apache生效:sudo apachectl restart - 检查PHP路径访问限制
新建phpinfo页面查看open_basedir配置项,确认目标img目录在PHP允许访问的路径范围内,如果存在路径限制,将img目录加入允许列表即可。
禁止将上传目录权限设置为0777,755权限配合正确的_www属主即可满足Web进程写入需求,同时避免其他系统用户随意篡改目录内文件。
内容的提问来源于stack exchange,提问作者P. James Norris
相关产品推荐
相关产品推荐

