注意,对于不存在的文件,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 'The file is writable';
} else {
echo 'The file is not writable';
}
?>
注意: 此函数的结果被缓存。有关详细信息,请参阅 clearstatcache()。
递归地检查目录是否可写。要返回 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));
}
}
?>
此 file_write() 函数将在写入 $content 之前为 $filename 提供写入权限。
注意,许多服务器不允许 PHP 用户更改文件权限。
<?php
function file_write($filename, &$content) {
if (!is_writable($filename)) {
if (!chmod($filename, 0666)) {
echo "Cannot change the mode of file ($filename)";
exit;
};
}
if (!$fp = @fopen($filename, "w")) {
echo "Cannot open file ($filename)";
exit;
}
if (fwrite($fp, $content) === FALSE) {
echo "Cannot write to file ($filename)";
exit;
}
if (!fclose($fp)) {
echo "Cannot close file ($filename)";
exit;
}
}
?>
对于 Darek 和 F Dot:关于组权限,在 php.ini 文件中有一段注释
; 默认情况下,安全模式在
; 打开文件时执行 UID 比较检查。如果您想放宽此限制为 GID 比较,
; 那么打开 safe_mode_gid。
safe_mode_gid = Off
看来 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
此函数的结果似乎没有被缓存
在 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;
?>
此函数在 windows 上检查网络驱动器时始终返回 false。
参见 PHP 错误 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 错误,该函数也能正常工作
// 注意:对于文件夹使用斜杠结尾!
// 参见 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 错误“不会修复”(参见 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 上都能正常工作
注意:您必须使用斜杠结尾来标识目录
函数 is_writable('ftp://user.....') 始终返回 false。我可以创建/删除文件,但我无法检查是否可写。这是 bug 还是 php 功能 :)?
检查目录是否可写。也适用于已挂载的 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