file_exists()返回false,但文件存在

时间:2011-08-03 16:52:38

标签: php windows apache wamp

我在使用file_exists()时遇到了一个非常奇怪的问题。我正在使用此功能来检查相同文件夹中是否存在2个不同的文件。我已经仔细检查了,他们确实存在。

echo $relative . $url['path'] . '/' . $path['filename'] . '.jpg';
Result: ../../images/example/001-001.jpg

echo $relative . $url['path'] . '/' . $path['filename'] . '.' . $path['extension'];
Result: ../../images/example/001-001.PNG

现在让我们在这些上使用file_exists():

var_dump(file_exists($relative . $url['path'] . '/' . $path['filename'] . '.jpg'));
Result: bool(false)

var_dump(file_exists($relative . $url['path'] . '/' . $path['filename'] . '.' . $path['extension']));
Result: bool(true)

我不明白 - 这两个文件都存在。我正在运行Windows,因此它与案例敏感问题无关。安全模式已关闭。

值得一提的是,.png文件是由用户通过FTP上传的,而.jpg文件是使用脚本创建的。但据我所知,这不应该有所作为。

任何提示?

由于

15 个答案:

答案 0 :(得分:20)

file_exists()的结果已缓存,因此请尝试使用clearstatcache()。如果没有帮助,请重新检查名称 - 它们可能相似,但不相同。

答案 1 :(得分:12)

这是因为安全模式。您可以将其关闭或包含safe_mode_include_dir中的目录。或者更改这些文件的文件所有权/权限。

php.net: file_exists()
php.net: safe mode

答案 2 :(得分:12)

我发现检查文件是否存在(相对于正在执行的当前php文件)的作用是这段代码:

$filename = 'myfile.jpg';
$file_path_and_name = dirname(__FILE__) . DIRECTORY_SEPARATOR . "{$filename}";
if ( file_exists($file_path_and_name) ){
  // file exists. Do some magic...              
} else {
  // file does not exists...
}

答案 3 :(得分:12)

file_exists()仅适用于HTTP地址。

它只支持文件系统路径(如果您使用PHP5,则支持FTP。)

请注意:

工作:

if  (file_exists($_SERVER['DOCUMENT_ROOT']."/folder/test.txt") 
    echo "file exists";

没有工作:

if (file_exists("www.mysite.com/folder/test.txt") 
    echo "file exists";

答案 4 :(得分:10)

只是我的$ .02:我刚遇到这个问题,这是由于文件名末尾有一个空格。它并不总是一个路径问题 - 虽然这是我检查的第一件事 - 总是如此。我可以使用ls -l命令将文件名剪切并粘贴到shell窗口中,当然,这会定位文件,因为命令行将忽略file_exists不存在的空间。确实非常令人沮丧,几乎不可能找到它,不适合StackOverflow。

提示:当输出调试语句时,使用分隔符()或[]包含值,这将非常清楚地显示空格。并且始终记得要减少你的输入。

答案 5 :(得分:2)

尝试使用DIRECTORY_SEPARATOR代替'/'作为分隔符。 Windows使用与Linux和Unix系统不同的文件系统路径(反斜杠)分隔符。

答案 6 :(得分:1)

它也可能是其中一个父文件夹或文件本身的权限问题。

尝试以运行Web服务器的用户身份打开会话并进入其中。该用户必须可以访问该文件夹,并且该文件必须是可读的。

如果没有,php将返回该文件不存在。

答案 7 :(得分:1)

这里有一个非常简单的技巧。

当我写下面一行时,它会返回false。

if(file_exists('/my-dreams-files/'.$_GET['article'].'.html'))

当我写删除URL开始斜杠时,它返回true。

if(file_exists('my-dreams-files/'.$_GET['article'].'.html'))

答案 8 :(得分:1)

我有一个新的原因会发生这种情况-我在一个Docker容器内使用PHP,该容器的代码库已安装在本地主机上。

我正在file_exists == FALSE(在Composer autoload内部)获得,但是如果我将filepath复制到终端中-它确实存在!我尝试了clearstatche(),并检查了安全模式是否关闭。

然后,我想起了Docker卷映射:本地主机上的绝对路径当然在Docker容器中不存在-这是PHP对世界的看法。

(我忘了我在使用Docker,因为我已经制作了可以很好地包装docker run命令的shell函数...)

答案 9 :(得分:0)

你试过手动输入吗?你的两个扩展似乎也有不同的情况

   var_dump(file_exists('../../images/example/001-001.jpg'));
   var_dump(file_exists('../../images/example/001-001.PNG'));

答案 10 :(得分:0)

一个custom_file_exists()函数受@Timur,@ Brian,@ Doug和@Shahar的启发以前的答案:

function custom_file_exists($file_path=''){
    $file_exists=false;

    //clear cached results
    //clearstatcache();

    //trim path
    $file_dir=trim(dirname($file_path));

    //normalize path separator
    $file_dir=str_replace('/',DIRECTORY_SEPARATOR,$file_dir).DIRECTORY_SEPARATOR;

    //trim file name
    $file_name=trim(basename($file_path));

    //rebuild path
    $file_path=$file_dir."{$file_name}";

    //If you simply want to check that some file (not directory) exists, 
    //and concerned about performance, try is_file() instead.
    //It seems like is_file() is almost 2x faster when a file exists 
    //and about the same when it doesn't.

    $file_exists=is_file($file_path);

    //$file_exists=file_exists($file_path);

    return $file_exists;
}

答案 11 :(得分:0)

这个答案可能有点hacky,但它一直在为我工作 -

$file = 'path/to/file.jpg';
$file = $_SERVER['REQUEST_SCHEME'].'://'.$_SERVER['HTTP_HOST'].'/'.$file;
$file_headers = @get_headers($file);
if($file_headers[0] == 'HTTP/1.1 404 Not Found') {
    $exists = false;
}else{
    $exists = true;
}

显然$_SERVER['REQUEST_SCHEME'] IIS 7.0 + PHP 5.3 一起使用有点冒险,所以你可以寻找一种更好的方法来添加协议。

我在http://php.net/manual/en/function.file-exists.php#75064

找到了这个答案

答案 12 :(得分:0)

我花了最后两个小时想知道我的if语句出了什么问题:file_exists($file)返回false,但我可以毫无问题地致电include($file)

事实证明我没有意识到我在include_path文件中设置的php .htaccess值没有转移到file_existsis_file,等

因此:

<?PHP
// .htaccess php_value include_path '/home/user/public_html/';

// includes lies in /home/user/public_html/includes/

//doesn't work, file_exists returns false
if ( file_exists('includes/config.php') )
{
     include('includes/config.php');
}

//does work, file_exists returns true
if ( file_exists('/home/user/public_html/includes/config.php') )
{
    include('includes/config.php');
}
?>

只是为了表明“简单的快捷方式”,比如在.htaccess中设置include_path,从长远来看可能会造成更多的悲痛。

答案 13 :(得分:0)

在我的情况下,问题是对file_exists()与符号链接和..(“ dotdot”或双倍句号)父目录引用的行为有误解。在这方面,它不同于requireinclude甚至是mkdir()之类的功能。

给出以下目录结构:

/home/me/work/example/
  www/
/var/www/example.local/
  tmp/
  public_html -> /home/me/work/example/www/

file_exists('/var/www/example.local/public_html/../tmp/');将返回FALSE,即使该子目录存在,因为该函数遍历到没有该子目录的/home/me/work/example/


由于这个原因,我创建了这个函数:

/**
 * Resolve any ".." ("dotdots" or double periods) in a given path.
 *
 * This is especially useful for avoiding the confusing behavior `file_exists()`
 * shows with symbolic links.
 *
 * @param string $path
 *
 * @return string
 */
function resolve_dotdots( string $path ) {

    if (empty($path)) {
        return $path;
    }

    $source = array_reverse(explode(DIRECTORY_SEPARATOR, $path));
    $balance = 0;
    $parts = array();

    // going backwards through the path, keep track of the dotdots and "work
    // them off" by skipping a part. Only take over the respective part if the
    // balance is at zero.
    foreach ($source as $part) {
        if ($part === '..') {
            $balance++;

        } else if ($balance > 0) {
            $balance--;

        } else {
            array_push($parts, $part);
        }
    }

    // special case: path begins with too many dotdots, references "outside
    // knowledge".
    if ($balance > 0) {
        for ($i = 0; $i < $balance; $i++) {
            array_push($parts, '..');
        }
    }

    $parts = array_reverse($parts);
    return implode(DIRECTORY_SEPARATOR, $parts);
}

答案 14 :(得分:0)

我刚刚遇到了同样的问题,并以一种神秘的方式解决了它。插入文件路径后,我从 Windows 文件资源管理器复制。 file_exists() 不断返回 false,但如果我从 VSCode 编辑器复制相同的路径,它可以完美运行。

使用 var_dump($path) 转储变量后;我注意到了一些神秘的东西。 对于我从文件资源管理器复制的路径,它显示长度为 94。 对于我从 VSCode 编辑器复制的路径,它显示长度为 88。

在我的代码编辑器中,两条路径的长度看起来相同。

我的建议:如果字符串包含隐藏字符,它可能会失败并且不起作用。