请注意,对于不存在的文件,is_writable 返回 false,尽管可以写入查询的路径。
(PHP 4, PHP 5, PHP 7, PHP 8)
is_writable — 判断文件名是否可写
如果 filename
存在且可写,则返回 true
。文件名参数可以是目录名,允许您检查目录是否可写。
请记住,PHP 可能会以 Web 服务器运行的用户 ID(通常为“nobody”)访问该文件。
filename
要检查的文件名。
如果 filename
存在且可写,则返回 true
。
失败时,会发出 E_WARNING
。
示例 #1 is_writable() 示例
<?php
$filename = 'test.txt';
if (is_writable($filename)) {
echo '文件可写';
} else {
echo '文件不可写';
}
?>
注意: 此函数的结果会被缓存。有关更多详细信息,请参阅 clearstatcache()。
对于 Darek 和 F Dot:关于组权限,php.ini 文件中有以下说明
; 默认情况下,安全模式在
; 打开文件时执行 UID 比较检查。如果您想将其放宽为 GID 比较,
; 那么请启用 safe_mode_gid。
safe_mode_gid = Off
递归检查目录是否可写。要返回 true,所有目录内容都必须可写
<?php
function is_writable_r($dir) {
if (is_dir($dir)) {
if(is_writable($dir)){
$objects = scandir($dir);
foreach ($objects as $object) {
if ($object != "." && $object != "..") {
if (!is_writable_r($dir."/".$object)) return false;
else continue;
}
}
return true;
}else{
return false;
}
}else if(file_exists($dir)){
return (is_writable($dir));
}
}
?>
看起来 is_writable() 不会检查文件的完整权限以确定当前用户是否可以写入它。例如,Apache 以用户“www”运行,并且是“wheel”组的成员,is_writable() 在类似这样的文件上返回 false:
-rwxrwxr-x root wheel /etc/some.file
关于您可能认识到您的 PHP 脚本构建的 Web 文件被分组为 NOBODY,您可以通过设置 FTP 连接(“ftp_connect”、“ftp_raw”等)并使用方法如“ftp_fput”来创建这些文件[而不是授予权限以便您可以使用通常的“不安全”方式]来避免此问题。这将使创建的文件不会获得 NOBODY 组 - 它也会获得 FTP 程序使用的 FTP 连接使用的组。
此外,您可能希望散列 FTP 连接的密码 - 然后查看
https://dev.mysqlserver.cn/doc/mysql/en/Password_hashing.html
此 file_write() 函数将在将 $content 写入它之前为 $filename 赋予写权限。
请注意,许多服务器不允许 PHP 用户更改文件权限。
<?php
function file_write($filename, &$content) {
if (!is_writable($filename)) {
if (!chmod($filename, 0666)) {
echo "无法更改文件模式 ($filename)";
exit;
};
}
if (!$fp = @fopen($filename, "w")) {
echo "无法打开文件 ($filename)";
exit;
}
if (fwrite($fp, $content) === FALSE) {
echo "无法写入文件 ($filename)";
exit;
}
if (!fclose($fp)) {
echo "无法关闭文件 ($filename)";
exit;
}
}
?>
此函数的结果似乎未被缓存
在 Linux 和 Windows 上测试
<?php
chmod($s_pathFichier, 0400);
echo'<pre>';var_dump(is_writable($s_pathFichier));echo'</pre>';
chmod($s_pathFichier, 04600);
echo'<pre>';var_dump(is_writable($s_pathFichier));echo'</pre>';
exit;
?>
在 Linux 中,您可能会遇到一个问题,即即使文件具有 644 权限,它也无法写入!问题在于 SELinux,只需禁用它或添加规则以允许它。
在 Windows 系统下,检查网络驱动器时,此函数始终返回 false。
参见 PHP Bug https://bugs.php.net/bug.php?id=68926
参见 https://stackoverflow.com/q/54904676
回复 Darek
我们有两台服务器:一台运行 PHP 5.0.4 和 Apache 1.3.33,另一台运行 PHP 4.3.5 和 Apache 1.3.27。PHP 4 服务器表现出您描述的行为,`is_writable()` 返回 'false',即使 www 用户属于拥有该文件的组,但 PHP 5 服务器返回 'true'。
这是我能想到的最新版本的 `is__writable()`。
它可以接受文件或文件夹,但是文件夹应该以尾部斜杠结尾!该函数尝试实际写入文件,因此当用户具有对它的ACL写访问权限时,它将正确返回 true。
<?php
function is__writable($path) {
// 将在 Windows ACLs bug 情况下工作
// 注意:文件夹需使用尾部斜杠!!!
//参见 http://bugs.php.net/bug.php?id=27609
//参见 http://bugs.php.net/bug.php?id=30931
if ($path{strlen($path)-1}=='/') // 递归返回临时文件路径
return is__writable($path.uniqid(mt_rand()).'.tmp');
else if (is_dir($path))
return is__writable($path.'/'.uniqid(mt_rand()).'.tmp');
// 检查临时文件的读写权限
$rm = file_exists($path);
$f = @fopen($path, 'a');
if ($f===false)
return false;
fclose($f);
if (!$rm)
unlink($path);
return true;
}
?>
由于看起来 Windows ACLs bug “不会修复”(参见 http://bugs.php.net/bug.php?id=27609),我建议使用此替代函数
<?php
function is__writable($path) {
if ($path{strlen($path)-1}=='/')
return is__writable($path.uniqid(mt_rand()).'.tmp');
if (file_exists($path)) {
if (!($f = @fopen($path, 'r+')))
return false;
fclose($f);
return true;
}
if (!($f = @fopen($path, 'w')))
return false;
fclose($f);
unlink($path);
return true;
}
?>
它应该在 *nix 和 Windows 系统上都能工作
注意:必须使用尾部斜杠来标识目录
检查目录是否可写。也可用于已挂载的 SMB 共享。
function isWritablePath($home, $xpath) {
$isOK = false;
$path = trim($xpath);
if ( ($path!="") && (strpos($path,$home)!==false) && is_dir($path) && is_writable($path) ) {
$tmpfile = "mPC_".uniqid(mt_rand()).'.writable';
$fullpathname = str_replace('//','/',$path."/".$tmpfile);
$fp = @fopen($fullpathname,"w");
if ($fp !== false) {
$isOK = true;
}
@fclose($fp);
@unlink($fullpathname);
}
return $isOK;
}
在 Windows 下,它只返回只读属性状态,而不是实际权限 (ACL)。
参见 http://bugs.php.net/bug.php?id=27609