PHP/IIS环境下file_get_contents读取上传文件遇权限拒绝问题求助
PHP上传文件后file_get_contents权限拒绝问题排查与解决
问题场景
文件成功上传至.../upload/tm/目录后,调用file_get_contents读取时触发500错误:权限拒绝。核心代码如下:
$target = 'upload/' . $data['folder'] . '/' . $filename; if (move_uploaded_file($file[$data['name']]['tmp_name'], $target)) { // $success = true; chmod($target, 0755); }
已调研情况
- 临时文件移动到目标目录时,不会继承
.../upload/tm/的权限,而是保留c:\windows\temp的权限配置 - 已确认
c:\windows\temp和.../upload/tm/的权限列表:IUSR、IIS_IUSRS、localmachine$、localmachine$/users等指定用户均拥有相同读写权限 - 手动重新应用
.../upload/tm/中IUSR的继承权限可临时解决,但无法作为长期自动化方案
临时 workaround(更新)
将临时上传文件夹改为网站目录树分支后,文件可正常访问读取。但仍希望保留原临时文件夹路径,需明确两个问题:
- 为何权限配置看似一致,
file_get_contents仍无法读取? - 如何在保留原临时文件夹路径的前提下彻底解决?
原因分析
- Windows权限的隐性差异:表面权限列表相同不代表有效权限一致:
c:\windows\temp是系统目录,权限受UAC、系统安全策略限制,部分用户权限是通过组间接继承,移动文件后这些间接权限不会被携带- IIS运行在应用池身份(默认是
IIS AppPool\应用池名称),而你检查的用户列表里大概率没包含这个核心身份——这才是PHP实际的运行身份
- move_uploaded_file的Windows特性:跨目录树移动文件时,不会自动应用目标目录的权限继承规则,而是保留源文件的DACL(自由访问控制列表)。如果源文件的DACL不包含PHP运行身份的读取权限,就会触发拒绝
解决方案
方案1:修复目标目录权限继承(推荐)
给.../upload/tm/配置强制权限继承,并确保应用池身份拥有读取权限:
- 右键
upload/tm目录 → 属性 → 安全 → 高级 - 勾选「替换所有子对象权限继承的权限条目」,点击应用
- 添加
IIS AppPool\[你的应用池名称]用户,授予读取&执行、列出文件夹内容、读取权限 - 代码中移除
chmod(0755)(Windows下chmod仅部分生效,优先依赖系统权限配置)
方案2:用复制替代移动
放弃move_uploaded_file,改用copy()+unlink()组合,复制文件会自动应用目标目录的权限继承:
$target = 'upload/' . $data['folder'] . '/' . $filename; if (copy($file[$data['name']]['tmp_name'], $target)) { unlink($file[$data['name']]['tmp_name']); // 清理临时文件 }
注意:需要确保临时目录和目标目录都有PHP运行身份的读写权限
方案3:修改PHP临时上传目录
在php.ini中修改upload_tmp_dir为网站目录树内的路径(比如C:\inetpub\wwwroot\your-site\temp-uploads),这样文件移动时处于同一目录树,权限会自动继承
内容的提问来源于stack exchange,提问作者Gubberrr
相关产品推荐
相关产品推荐

