注意:此函数的结果会被缓存。有关更多详细信息,请参阅 clearstatcache()。
这是一个非常重要的注意事项。不要忘记这一点,因为它可能会导致您的 file_exists() 行为异常 - 可能是生产环境中;)
(PHP 4, PHP 5, PHP 7, PHP 8)
file_exists — 检查文件或目录是否存在
filename
文件或目录的路径。
在 Windows 上,使用 //computername/share/filename 或 \\computername\share\filename 检查网络共享上的文件。
如果由 filename
指定的文件或目录存在,则返回 true
;否则返回 false
。
注意:
此函数将对指向不存在文件的符号链接返回
false
。
注意:
检查使用的是真实的 UID/GID,而不是有效的 UID/GID。
注意: 由于 PHP 的整数类型是有符号的,并且许多平台使用 32 位整数,因此对于大于 2GB 的文件,某些文件系统函数可能会返回意外的结果。
失败时,会发出 E_WARNING
。
示例 #1 测试文件是否存在
<?php
$filename = '/path/to/foo.txt';
if (file_exists($filename)) {
echo "文件 $filename 存在";
} else {
echo "文件 $filename 不存在";
}
?>
注意: 此函数的结果会被缓存。有关更多详细信息,请参阅 clearstatcache()。
注意:此函数的结果会被缓存。有关更多详细信息,请参阅 clearstatcache()。
这是一个非常重要的注意事项。不要忘记这一点,因为它可能会导致您的 file_exists() 行为异常 - 可能是生产环境中;)
请注意,如果文件不存在,realpath() 将返回 false。因此,如果您打算无论如何都要将路径绝对化并解析符号链接,则可以只检查 realpath() 的返回值,而不是首先调用 file_exists()。
我需要为一个项目衡量性能,所以我用一百万个 file_exists() 和 is_file() 检查进行了简单的测试。在一个场景中,只有七个文件存在。在第二个场景中,所有文件都存在。is_file() 需要 3.0 秒来完成第一个场景,3.3 秒来完成第二个场景。file_exists() 分别需要 2.8 秒和 2.9 秒。绝对数字当然与系统相关,但它清楚地表明 file_exists() 更快。
针对 seejohnrun 检查 URL 是否存在的版本。即使文件不存在,您仍然会收到 404 标头。如果您没有使用 CURL 的选项,您仍然可以使用 get_headers..
$file = 'http://www.domain.com/somefile.jpg';
$file_headers = @get_headers($file);
if($file_headers[0] == 'HTTP/1.1 404 Not Found') {
$exists = false;
}
else {
$exists = true;
}
file_exists() 不会在 php include_path 中搜索您的文件,因此在尝试 include 或 require 之前不要使用它。
使用
@$result = include $filename;
是的,当找不到文件时,include 会返回 false,但它也会生成警告。这就是为什么你需要 @ 的原因。不要试图通过使用 file_exists() 来绕过警告问题。这会让你抓耳挠腮,直到你弄清楚或偶然发现 file_exists() 不会搜索 PHP INCLUDE_PATH 的事实。
我编写了这个方便的小函数来检查图像是否在目录中存在,如果存在,则返回一个不存在的文件名,例如,如果您尝试“flower.jpg”并且它存在,那么它将尝试“flower[1].jpg”,如果该文件存在,则它将尝试“flower[2].jpg”,依此类推。在我的地方运行良好。当然,您也可以将其用于除图像之外的其他文件类型。
<?php
function imageExists($image,$dir) {
$i=1; $probeer=$image;
while(file_exists($dir.$probeer)) {
$punt=strrpos($image,".");
if(substr($image,($punt-3),1)!==("[") && substr($image,($punt-1),1)!==("]")) {
$probeer=substr($image,0,$punt)."[".$i."]".
substr($image,($punt),strlen($image)-$punt);
} else {
$probeer=substr($image,0,($punt-3))."[".$i."]".
substr($image,($punt),strlen($image)-$punt);
}
$i++;
}
return $probeer;
}
?>
在 Ubuntu 17.04 上使用 PHP 7.0 并且开启了 allow_url_fopen=On 选项后,当尝试通过 HTTP 检查远程文件时,file_exists() 总是返回 false。
所以
$url="http://www.somewhere.org/index.htm";
if (file_exists($url)) echo "Wow!\n";
else echo "missing\n";
总是返回 "missing",即使 URL 存在。
我发现在相同情况下,file() 函数可以读取远程文件,所以我将我的程序改成了
$url="http://www.somewhere.org/index.htm";
if (false!==file($url)) echo "Wow!\n";
else echo "missing\n";
这显然有点慢,特别是如果远程文件很大,但它解决了这个问题。
如果您尝试访问 Windows 网络共享,则必须为您的 Web 服务器配置足够的权限,例如
$file = fopen("\\siscomx17\c\websapp.log",'r');
您将收到一条错误消息,提示路径名不存在,这是因为 Apache 或 IIS 以 LocalSystem 身份运行,因此您必须进入服务并配置 Apache 的“以…身份打开会话”,创建一个具有足够权限的新用户,并确保目标共享具有正确的权限。
希望这能为任何人节省几个小时的研究时间。
file_exists() 易受竞争条件的影响,而 clearstatcache() 无法有效避免这种情况。
以下函数是一个很好的解决方案
<?php
function file_exists_safe($file) {
if (!$fd = fopen($file, 'xb')) {
return true; // 文件已存在
}
fclose($fd); // 文件已创建,我们不需要文件句柄
return false;
}
?>
如果文件不存在,该函数将创建一个文件,后续调用将失败,因为文件已存在(实际上是一个锁)。
重要提示:如果文件成功创建,它将保留在磁盘上,您必须自行清理,例如删除它或覆盖它。此步骤有意从函数中省略,以便脚本在确保文件不会被其他进程“占用”的同时执行计算。
注意:如果所有其他脚本/进程都没有使用上述函数进行检查,则此方法将失败,因为它实际上并没有锁定文件。
修复:您可以使用 flock() 锁定文件以防止这种情况发生(尽管所有其他脚本也必须使用 flock() 检查它,请参见 https://php.net/manual/en/function.flock.php)。确保在完成使用文件后解锁并关闭文件,而不是在上述函数中。
<?php
function create_and_lock($file) {
if (!$fd = fopen($file, 'xb')) {
return false;
}
if (!flock($fd, LOCK_EX|LOCK_NB)) { // 可能因其他原因失败,LOCK_NB 将防止阻塞
fclose($fd);
unlink($file); // 清理
return false;
}
return $fd;
}
if ($lock = create_and_lock("foo.txt")) {
// 执行操作
flock($fd, LOCK_UN); // 解锁
fclose($fd); // 关闭
}
?>
另请参阅:https://linux.die.net/man/2/open 有关 O_CREAT|O_EXCL(与 fopen() 的“x”修饰符一起使用)以及 NFS 相关的问题
我编写了一段代码,用于查看通过 RTSP 提供的文件是否存在。
<?php
function rtsp_exists($url) {
$server = parse_url($url, PHP_URL_HOST);
$port = "554";
$hdrs = "DESCRIBE " .$url ." RTSP/1.0"."\r\n\r\n";
// 打开连接(15 秒超时)
$sh = fsockopen($server, $port, $err, $err_otp, 15);
// 检查连接
if(!$sh) return false;
// 发送头部
fputs($sh,$hdrs);
// 接收数据(1KB)
$rtds = fgets($sh, 1024);
// 关闭套接字
fclose($sh);
return strpos($rtds, "200 OK") > 0;
}
?>
由于某种原因,此处发布的 url_exists() 函数都不适合我,因此这是我自己的调整版本。
<?php
function url_exists($url){
$url = str_replace("http://", "", $url);
if (strstr($url, "/")) {
$url = explode("/", $url, 2);
$url[1] = "/".$url[1];
} else {
$url = array($url, "/");
}
$fh = fsockopen($url[0], 80);
if ($fh) {
fputs($fh,"GET ".$url[1]." HTTP/1.1\nHost:".$url[0]."\n\n");
if (fread($fh, 22) == "HTTP/1.1 404 Not Found") { return FALSE; }
else { return TRUE; }
} else { return FALSE;}
}
?>
这是一个检查特定 URL 是否存在的函数
<?php
函数 url_exists($url) {
$a_url = parse_url($url);
if (!isset($a_url['port'])) $a_url['port'] = 80;
$errno = 0;
$errstr = '';
$timeout = 30;
if(isset($a_url['host']) && $a_url['host']!=gethostbyname($a_url['host'])){
$fid = fsockopen($a_url['host'], $a_url['port'], $errno, $errstr, $timeout);
if (!$fid) return false;
$page = isset($a_url['path']) ?$a_url['path']:'';
$page .= isset($a_url['query'])?'?'.$a_url['query']:'';
fputs($fid, 'HEAD '.$page.' HTTP/1.0'."\r\n".'Host: '.$a_url['host']."\r\n\r\n");
$head = fread($fid, 4096);
fclose($fid);
return preg_match('#^HTTP/.*\s+[200|302]+\s#i', $head);
} else {
return false;
}
}
?>
在我的CMS中,我使用以下代码行
<?php
if(!isset($this->f_exist[$image]['exist']))
if(strtolower(substr($fimage,0,4)) == 'http' || strtolower(substr($fimage,0,4)) == 'www.'){
if(strtolower(substr($image,0,4)) == 'www.'){
$fimage = 'http://'.$fimage;
$image = 'http://'.$image;
}
$this->f_exist[$image]['exist'] = $this->url_exists($fimage); //目前为止
} else {
$this->f_exist[$image]['exist'] = ($fimage!='' && file_exists($fimage) && is_file($fimage) && is_readable($fimage) && filesize($fimage)>0);
}
}
?>
您可以使用文档根目录以确保安全,因为该函数不接受相对路径。
<?php
if( file_exists( $_SERVER{'DOCUMENT_ROOT'} . "/my_images/abc.jpg")) {
...
}
?>
不要忘记加上斜杠“/”,例如,我在Ubuntu中的文档根目录是/var/www,没有斜杠。
使用file_exists时,似乎无法执行以下操作
<?php
foreach ($possibles as $poss)
{
if ( file_exists(SITE_RANGE_IMAGE_PATH .$this->range_id .'/ '.$poss .'.jpg') )
{
// 存在
}
else
{
// 未找到
}
}
?>
所以您必须执行以下操作
<?php
foreach ($possibles as $poss)
{
$img = SITE_RANGE_IMAGE_PATH .$this->range_id .'/ '.$poss .'.jpg'
if ( file_exists($img) )
{
// 存在
}
else
{
// 未找到
}
}
?>
然后一切都会正常工作。
至少在运行php 5.2.5和apache 2.2.3的此Windows系统上是这种情况。
不确定是连接还是其中存在常量导致的,我准备离开并进行测试……
如果文件权限未为“其他”启用读取权限(而非您的php用户拥有),则file_exists将无法找到您的文件。我以为我在处理目录名称中包含空格的问题(/users/andrew/Pictures/iPhoto Library/AlbumData.xml),但实际上是Pictures、iPhoto Library或AlbumData.xml没有读取权限。一旦我修复了它,file_exists就起作用了。
此处的代码用于检查文件是否在另一台服务器上存在
<?php
function fileExists($path){
return (@fopen($path,"r")==true);
}
?>
不幸的是,file_exists无法访问远程服务器,所以我使用了fopen函数。
关于openspecies条目(顺便说一句,非常棒,谢谢!)。
如果您的服务器无法解析自己的DNS,请使用以下代码
$f = preg_replace('/www\.yourserver\.(net|com)/', getenv('SERVER_ADDR'), $f);
就在$h = @get_headers($f);行之前。
根据需要替换正则表达式中的扩展名(net|com|...)。
示例
您要检查的文件:http://www.youserver.net/myfile.gif
服务器IP:10.0.0.125
preg_replace将有效地为您“解析”地址,如下所示分配$f
http://10.0.0.125/myfile.gif
这是一个更简单的url_exists版本
<?php
function url_exists($url) {
$hdrs = @get_headers($url);
return is_array($hdrs) ? preg_match('/^HTTP\\/\\d+\\.\\d+\\s+2\\d\\d\\s+.*$/',$hdrs[0]) : false;
}
?>
该代码可用于测试文件名,该文件名可用于创建新的文件名。
<?php
function generateRandomString($length = 8)
{
$string = "";
//可使用的字符
$possible = "0123456789bcdfghjkmnpqrstvwxyz";
for($i=0;$i < $length;$i++)
{
$char = substr($possible, rand(0, strlen($possible)-1), 1);
if (!strstr($string, $char))
{
$string .= $char;
}
}
return $string;
}
function randomFile($folder = '', $extension = '')
{
$folder = trim($folder);
$folder = ($folder == '') ? './' : $folder;
//检查目录是否存在
if (!is_dir($folder)){ die('提供的文件夹无效!'); }
//生成文件路径
$filepath = $folder . "/" . generateRandomString(128) . $extension;
//检查该文件路径是否已存在,如果存在则再次生成
//直到得到一个不存在的文件路径
while(file_exists($filepath))
{
$filepath = $folder . "/" . generateRandomString(128) . $extension;
}
return $filepath;
}
?>
如果您怀疑正在测试的文件路径包含空格,请**不要**用单引号或双引号将路径括起来。file_exists() 会将引号解释为属于文件路径的字符。相反,什么都不做:file_exists() 会代表您正确地转义空格。
注意:此函数需要完整的服务器相关路径名才能正常工作。
例如,如果您从网站的根文件夹内部运行 PHP 例程,并请求
$bstr = file_exists("/images/Proofreading_patients.jpg");
即使该文件确实存在于根目录之外,您也会得到 FALSE。
您需要添加
$bstr = file_exists(__DIR_."/images/Proofreading_patients.jpg");
才能使其返回 TRUE - 即:/srv/www/mywebsite.com/public/images/Proofreading_patients.jpg
我在使用 url 时遇到 file_exists 的问题,所以我创建了这个函数
<?php
function file_exists_2($filePath)
{
return ($ch = curl_init($filePath)) ? @curl_close($ch) || true : false;
}
?>
干杯!
file_exists() 将对损坏的链接返回 FALSE
$ ln -s does_not_exist my_link
$ ls -l
lrwxr-xr-x 1 user group 14 May 13 17:28 my_link -> does_not_exist
$ php -r "var_dump(file_exists('my_link'));"
bool(false)
以下脚本检查是否存在具有相同名称的文件,并在文件名末尾添加 _n,其中 n 增加。如果 img.jpg 位于服务器上,则尝试使用 img_0.jpg,检查它是否位于服务器上,然后尝试使用 img_1.jpg。
<?php
$img = "images/".$_FILES['bilde']['name'];
$t=0;
while(file_exists($img)){
$img = "images/".$_FILES['bilde']['name'];
$img=substr($img,0,strpos($img,"."))."_$t".strstr($img,".");
$t++;
}
move_uploaded_file($_FILES['bilde']['tmp_name'], $img);
?>
如果 file_exists() 正在测试的文件位于符号链接的目录结构中,则结果取决于链接树下方的目录树节点的权限。Web 服务器(例如 apache)下的 PHP 将尊重符号链接下文件系统的权限,这与作为 shell 脚本的 PHP(尊重链接的目录的权限,即顶部和可见的目录)形成对比。
这会导致文件在符号链接上似乎不存在,即使它们确实存在并且实际上可以被 Web 服务器读取。
我花了两个小时才弄清楚我的 if 语句哪里出错了:file_exists($file) 返回 false,但是我可以毫无问题地调用 include($file)。
事实证明,我并没有意识到我在 .htaccess 文件中设置的 php include_path 值没有传递给 file_exists、is_file 等。
因此
<?PHP
// .htaccess php_value include_path '/home/user/public_html/';
// includes 位于 /home/user/public_html/includes/
//不起作用,file_exists 返回 false
if ( file_exists('includes/config.php') )
{
include('includes/config.php');
}
//起作用,file_exists 返回 true
if ( file_exists('/home/user/public_html/includes/config.php') )
{
include('includes/config.php');
}
?>
这说明“为了简单而采取的捷径”,比如在 .htaccess 中设置 include_path,从长远来看只会造成更多麻烦。
Wordpress 总是将完整 URL 添加到它存储在数据库中的任何文件中,因此,如其他地方所述,file_exists() 找不到该文件,因为它使用的是“文档根目录”,而不是 URL。一个简单的解决方法是使用
file_exists (str_replace (home_url(), $_SERVER['DOCUMENT_ROOT'], $file) )
来检查文件 $file 是否存在。注意:从 PHP8 开始,'DOCUMENT_ROOT' 必须用方括号括起来,而不是像 ferodano at gmail dot com 所建议的那样用大括号括起来。
或者,如果不使用 WP,请将上面的 home_url() 替换为绝对 URL 名称,例如 'https://mywebsite.com' - 用引号括起来,并且没有尾随斜杠。
旧版 php(v4.x)不适用于 get_headers() 函数。所以我创建了这个,并且可以工作。
<?php
function url_exists($url) {
// 支持 4.x 版本
$handle = curl_init($url);
if (false === $handle)
{
return false;
}
curl_setopt($handle, CURLOPT_HEADER, false);
curl_setopt($handle, CURLOPT_FAILONERROR, true); // 这有效
curl_setopt($handle, CURLOPT_NOBODY, true);
curl_setopt($handle, CURLOPT_RETURNTRANSFER, false);
$connectable = curl_exec($handle);
curl_close($handle);
return $connectable;
}
?>