【问题标题】:file_exists() returns false, but the file DOES existfile_exists() 返回 false,但文件确实存在
【发布时间】:2011-10-19 07:09:33
【问题描述】:

我在使用 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 文件是使用脚本创建的。但据我所知,这应该没什么区别。

有什么建议吗?

谢谢

【问题讨论】:

  • 对我来说它最终是因为它需要绝对路径,而不是相对路径。一些 PHP 函数接受相对于当前文件的路径,其中一个是 parse_ini_file。
  • 我也以为我有这个问题。检查拼写 10 次后,我意识到文件名以“.jpg.jpg”结尾。没错,我是个失败者

标签: php windows apache wamp


【解决方案1】:

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

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

在我的代码编辑器上,两条路径的长度相同。

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

    • DIRECTORY_SEPARATOR?
    • 是的,@happy_marmoset。我更正了答案。谢谢!
    【解决方案3】:

    在我的情况下,问题是对 file_exists() 如何处理符号链接和 ..(“点点”或双句点)父目录引用的误解。在这方面,它不同于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);
    }
    

    【讨论】:

      【解决方案4】:

      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";
      

      【讨论】:

      • 在我的情况下 PHP 版本是 7.1.2 bu 相同的问题。您的回答正确且有效。
      • 谢谢,我就是这样。
      【解决方案5】:

      我发现检查文件是否存在(相对于正在执行的当前 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...
      }
      

      【讨论】:

      • 我遇到了一个问题,为了解决这个问题,我确保路径不是以 /
      【解决方案6】:

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

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

      【讨论】:

      • 安全模式已经关闭,所以这不是问题。此外,权限应该是特定于文件的,因为它们都在同一个文件夹中。我在 Windows 中从未遇到过这些问题,但是在查看权限时,我看不出两者之间有什么区别......
      • 啊,抱歉没有看到安全模式已关闭。如果权限相同,您可能需要检查这些文件的所有者 ID 或组 ID,可能是您的网络用户不属于该组或不是该文件的所有者。
      • 请注意,在 PHP 5.4.0 中删除了 safe_mode。
      【解决方案7】:

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

      原来我没有意识到我在.htaccess文件中设置的phpinclude_path值并没有延续到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,从长远来看只会造成更多的痛苦。

      【讨论】:

        【解决方案8】:

        我有一个发生这种情况的新原因 - 我在 Docker 容器中使用 PHP,并为驻留在本地主机上的代码库安装了卷。

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

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

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

        【讨论】:

        • 我想投票 1000 次!我花了几个小时认为这是一个权限问题,但我需要做的就是将我的 PHP 脚本从 /Volumes/MyDrive 重新映射到 /var/www/html。谢谢提醒
        • 我也有同样的问题。不是 Docker 专家,我不确定如何重新映射。当我尝试 $iRc=file_exists("/opt/docker-substantiator/app/assets/image_crud/views/list.php");,这是主机上的完整路径时,它失败了。当然在 cmd 行上 ls /opt/docker-substantiator/app/assets/image_crud/views/list.php 工作正常。我的容器中 list.php 的路径应该是什么?
        • @RichardBernstein 这取决于您如何安装卷。您只需要确保您的应用程序使用的路径符合容器的文件系统,而不是主机的。我会跳进去使用docker exec -it container-name bash 检查它是否正确,然后四处寻找,直到您了解内部文件系统。您可以从卷映射中找出它(例如 -v /Volumes/MyDrive:/var/www/html),但看到它的位置会更清楚。
        • @RichardBernstein 但如果您的路径 /opt/docker-substantiator/app/assets/image_crud/views/list.php 在容器中是正确的(即它不是您的主机/开发机器上的路径),那么您可能会遇到不同的问题。
        • 感谢 scipilot。我认为问题在于您所说的映射。我加载了 bash,我看到了:/app#。我想我需要学习查看内部文件系统的命令。我没有创建原始容器,所以我不知道 docker run 从哪里得到它的安装指令。再次感谢。
        【解决方案9】:

        这个答案可能有点老套,但它对我有用 -

        $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

        【讨论】:

          【解决方案10】:

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

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

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

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

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

          【讨论】:

          • 这似乎是意料之中的,前提是 my-dreams-files 不在驱动器的根目录中。 / 前面没有任何内容是根。你的第二个例子是相对的。
          【解决方案11】:

          也可能是某个父文件夹或文件本身的权限问题。

          尝试以运行您的网络服务器的用户身份打开一个会话并 cd 进入它。该用户必须可以访问该文件夹,并且该文件必须是可读的。

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

          【讨论】:

            【解决方案12】:

            受@Timur、@Brian、@Doug 和@Shahar 先前答案启发的 custom_file_exists() 函数:

            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;
            }
            

            【讨论】:

            • 你缺少custom_basename函数声明
            • 感谢 chumkiu basename() 在这种情况下就足够了
            【解决方案13】:

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

            提示:当输出调试语句时,用分隔符 () 或 [] 将值括起来,这样会很清楚地显示一个空格。并且永远记得修剪你的输入。

            【讨论】:

            • 当然我找到了这个答案之后我自己解决了这个完全相同的问题!
            • 最好使用 trim()。每次都能吸引我。
            【解决方案14】:

            您是否尝试过手动输入。您的两个扩展名似乎也不同

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

            【讨论】:

              【解决方案15】:

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

              【讨论】:

              • 这确实是问题所在。脚本似乎用 - 替换了 _。很难错过(也很烦人):|
              • 有时也会发生类似的事情:)
              • 对我来说 clearstatcache() - 没有帮助,但是......我的班级名称是 Multimedia。然后我使用 clearstatcache() - 仍然没有工作。然后我将文件重命名为 Multimedia2 并没有帮助。那很奇怪。然后我将文件重命名为 Abc。它起作用了...然后重命名为 Multimedia 并再次起作用:D 我花了大约半个小时...
              • 我也有这些问题。因为我提供了file_exists() 完整路径。它不应该是完整的路径。例如 www.abc.com/photo.jpg,你应该只提供 photo.jpg 而不是域。
              • clearstatcache() 在这里没有用:根据文档,PHP 不会缓存有关不存在文件的信息。因此,如果 file_exists 返回 false 而不是 true,则文件状态缓存与此无关。另一方面,如果 file_exists 返回 true 或 false,则 clearstatecache 可能是一个解决方案。 @见php.net/manual/en/function.clearstatcache.php
              猜你喜欢
              • 2016-01-13
              • 2014-01-02
              • 2012-01-31
              • 2017-08-15
              • 2017-08-16
              • 2011-06-05
              • 2012-09-02
              • 2015-09-14
              • 2012-05-13
              相关资源
              最近更新 更多