【问题标题】:file_exists() not working in php5 inside while loopfile_exists() 在 while 循环内的 php5 中不起作用
【发布时间】:2017-11-09 12:34:38
【问题描述】:

file_exists 不工作。我看了几个例子,还是不行。程序未检测到该文件。我的文件路径是/var/www/osbs/PHPAPI/recording.mp3,网站根目录在osbs里面。该文件的位置在 PHPAPI 中,这就是为什么我没有将完整路径放在 file_put_contents 中的原因。该程序能够制作原始的recording.mp3,但不能制作它的任何附加版本。

<?php
$actual_name = pathinfo("PHPAPI/recording.mp3",PATHINFO_FILENAME);
$original_name = $actual_name;
$extension = pathinfo("PHPAPI/recording.mp3",PATHINFO_EXTENSION);

if ($_GET["RecordingUrl"]) {
     if (file_exists("/var/www/osbs/PHPAPI/".$actual_name.".".$extension)) {
        $actual_name = find_new_name($original_name, $extension);
     }
     else {
        $actual_name = $original_name;
     }
     $name = $actual_name.".".$extension;
     file_put_contents($name, file_get_contents($_GET["RecordingUrl"]));
}

function find_new_name ( $file, $extension ) {
    $name = $file.".".$extension;
    $i = 0;
    while(file_exists("/var/www/osbs/PHPAPI/".$name)){
        $new_name = $file.$i;
        $name = $new_name.".".$extension;
        $i++;
    }
    return $new_name;
}
 ?>

【问题讨论】:

  • 这是一个巨大的安全问题:file_get_contents($_GET["RecordingUrl"])
  • @greg0ire 我知道这只是为了测试。我通常会使用 $_POST
  • 你太搞笑了
  • 直接传递任何用户输入的 file_get_contents() 存在安全风险。

标签: php if-statement while-loop get


【解决方案1】:

您的问题与file_put_contents 有关。您需要指定一个完整路径,并且您只指定一个文件名。在使用之前尝试echoing $name,你会发现它不是路径,只是文件名。

我建议您在文件开头设置一个带有路径的常量,而不是有时依赖相对路径,有时依赖绝对路径。

<?php
const SAVE_PATH = "/var/www/osbs/";

$actual_name = pathinfo(SAVE_PATH."PHPAPI/recording.mp3",PATHINFO_FILENAME);
$original_name = $actual_name;
$extension = pathinfo(SAVE_PATH."PHPAPI/recording.mp3",PATHINFO_EXTENSION);

if (isset($_GET["RecordingUrl"]) && $_GET["RecordingUrl"]) {
     if (file_exists(SAVE_PATH."PHPAPI/".$actual_name.".".$extension)) {
        $actual_name = find_new_name($original_name, $extension);
     }
     else {
        $actual_name = $original_name;
     }
     $name = $actual_name.".".$extension;

     file_put_contents(SAVE_PATH.'PHPAPI/'.$name, file_get_contents($_GET["RecordingUrl"]));
}

function find_new_name ( $file, $extension ) {
    $name = $file.".".$extension;
    $i = 0;
    while(file_exists(SAVE_PATH."PHPAPI/".$name)){
        $new_name = $file.$i;
        $name = $new_name.".".$extension;
        $i++;
    }
    return $new_name;
}
 ?>

我改变了什么:

  1. 定义了const SAVE_PATH = "/var/www/osbs/";
  2. 在任何地方都使用新常量。不再有时而相对,时而绝对,一切都是绝对的。
  3. file_put_contents 中使用了常量(这是实际修复,您需要一个完整的路径
  4. 添加了一个额外的检查来确保RecordingUrl isset,否则当它没有设置时你会得到一个PHP警告。

【讨论】:

    【解决方案2】:

    问题似乎出在脚本的第一行:

    $actual_name = pathinfo("PHPAPI/recording.mp3", PATHINFO_FILENAME);
    

    这会将recording.mp3 分配给$actual_filename。然后,您通过将扩展名连接到文件名来检查recording.mp3.mp3。我想你想使用PATHINFO_BASENAME 它将返回文件名无扩展名。

    【讨论】:

    • 这没有帮助。即使我将路径更改为 (file_exists("/PHPAPI/recording.mp3")) file_exists 仍然失败
    • 您的include path 可能不包含包含 PHPAPI 文件夹的目录。转储 get_include_path 以获取它将查找文件夹的目录列表,如果根目录不在其中,则需要先添加它或使用文件夹的完整路径。
    【解决方案3】:

    您确定路径吗? /PHPAPI/PHPAPI 中查找文件,而不是预期的 /var/www/osbs/PHPAPI/。你应该检查PHPAPI/$filename

    【讨论】:

    • /var/www/osbs/PHPAPI 是通过 SSH 连接到服务器的完整路径,但是,该域的 apache 文档根目录是 osbs 文件夹。所以 /PHPAPI 是文件夹,recording.mp3 是它应该寻找的原始文件。 /PHPAPI/recording.mp3 是路径。如果原始文件不存在,则从 $_GET 创建它,但如果它确实存在,则将计数器编号附加到它
    • 这没有提供问题的答案。要批评或要求作者澄清,请在他们的帖子下方留下评论。 - From Review
    • @Talus 这不是真的,PHP 脚本采用域的 Apache webroot。如果是这种情况,文件将不会被创建。
    • 再一次,不。 file_exists 不在乎。 url 地址中的任何内容对 php 都无关紧要。试试__DIR__,它是包含当前文件的目录的完整路径,它不会给你/,而是/var/www/osbs所有 PHP 中的文件函数的工作方式大致相同:它需要真实 路径(或当前脚本的相对路径,以简化)。 realpath('/PHPAPI/...') 应该返回 null 或类似的东西,没有您期望的路径,而 realpath(__DIR__ . '/PHPAPI/...) 将返回您期望的路径。 file_exists 也是一样。
    • php 是一种通用语言,您的代码可以从 CLI 运行,这显然不知道您的文档根目录。您将了解路径与 url 有何不同
    【解决方案4】:

    你必须把你所有的逻辑都放在find_new_name() 函数中。这将使您的代码更清晰

    if ($_GET["RecordingUrl"]) {
      $name = find_new_name("PHPAPI/recording.mp3");
      file_put_contents($name, file_get_contents($_GET["RecordingUrl"]));
    }
    
    function find_new_name($name) {
      $info = pathinfo($name);
      $name = $info['basename'];
      $i = 0;
      while (file_exists("$info[dirname]/$name")) {
        $name = sprintf('%s%d.%s', $info['filename'], ++$i, $info['extension']);
      }
      return "$info[dirname]/$name";
    }
    

    【讨论】:

    • 只有回答指出这一点,我会说这是罪魁祸首。 Sane 功能 FTW。但是我必须承认,这可以进一步改进,以便可以重新使用文件名中的现有数字,并且如果在检测到免费(例如并行上传)后创建文件,该功能可以继续找到 next 新名称。
    【解决方案5】:

    您忘记了 file_put_contents() 的路径。 应该是:

    file_put_contents("PHPAPI/".$name, file_get_contents($_GET["RecordingUrl"]));
    

    或者:

    file_put_contents("/var/www/osbs/PHPAPI/".$name, file_get_contents($_GET["RecordingUrl"]));
    

    【讨论】:

      【解决方案6】:

      您对文件的 URL 和它的 PATH

      感到困惑

      您的 httdoc(或 public_html )根目录是 /var/www/osbs/PHPAPI

      但您的文件系统根目录是 '/'

      试试

      file_put_contents( __DIR__.'/'.$name, file_get_contents($_GET["RecordingUrl"]));
      

      你的代码中有很多不好的做法

      【讨论】:

        【解决方案7】:

        'file_exists' 和其他一些文件调用(如 fstat)由 php 缓存。这记录在 file_exists 的手册中。当文件不存在时您的第一次调用将被保存并在后续调用中返回。在调用之间使用“clearstatcache()”来清除缓存。

        【讨论】:

          【解决方案8】:

          一个“小”重构:

          1. 无处不在的绝对路径
          2. 函数透明,名称更一目了然,参数使用更简单
          3. 防止恶意输入($_POST 确实不适合)
          4. 为什么要实际复制()时使用file_put_contents()

            <?php
            
            define("SRC_PATH", "/var/www/osbs/whereverYourSrcIs/");
            define("SAVE_PATH", "/var/www/osbs/PHPAPI/");
            
            function findAvailableName($name) {
                $i = 1;
                $pathinfo = pathinfo($name);
                while(file_exists($name)) {
                    $name = $pathinfo['dirname'] . '/' . $pathinfo['filename'] . "." . $i++ . "." . $pathinfo['extension'];
                }
                return $name;
            }
            
            if (isset($_GET["RecordingUrl"]) && $_GET["RecordingUrl"]) {
            
                if (strpos('/' . $_GET['RecordingUrl'] . '/', '/../') !== false) {
                    die("invalid input, don't be evil");
                }
            
                copy(SRC_PATH . $_GET["RecordingUrl"], findAvailableName(SAVE_PATH . "recording.mp3"));
            }
            

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2018-06-12
            • 2011-10-19
            • 1970-01-01
            • 2015-08-02
            • 2017-11-13
            • 1970-01-01
            • 2017-05-01
            相关资源
            最近更新 更多