为什么当所有其他元素都正确时,此对 fopen 的调用会失败


Why does this call to fopen fail when all the other elements appear correct?

是的,另一个关于fopen()的问题...有数百个,但没有一个得到这个。这个问题很相似,但是在尝试了答案(检查权限,检查树是否存在)后,我仍然有这个问题。

当尝试使用 fopen 创建文件时,我调用该函数并为其提供所需的参数,但它会抛出警告:"没有这样的文件或目录"。但是,检查树会发现目录确实存在。代码是这样的:

$target_dir = "/files/" . usernameIs() . "/";
$target_file = $target_dir . basename($_FILES["uploadedFile"]["name"]);
...
$file = fopen($target_file, "w+");
fclose($file);

$target_file最终包含/files/ArtOfCode/icon.png(用户名是ArtOfCode,我用来测试的uploadedFilename是icon.png。

目录树如下所示:

public_html
  > /upload
    > /upload.php        (the calling script)
    > /action.php        (this script)
  > /files
    > /ArtOfCode

我收到两个警告,都与fopen()有关:

Warning: fopen(/files/ArtOfCode/icon.png): failed to open stream: No such file or directory in /home/u875642593/public_html/upload/action.php on line 26
Warning: fclose() expects parameter 1 to be resource, boolean given in /home/u875642593/public_html/upload/action.php on line 27

所以,我知道该文件(/files/ArtOfCode/icon.png)不存在。但是,PHP 文档说"...如果该文件不存在,fopen将在尝试使用它之前创建它。支持目录树确实存在,所以我被难住了。如何使此调用创建文件?

PHP 的文件系统函数(如 fopen() 及其兄弟姐妹)在文件系统路径上运行,而不是相对于 Web 服务器文档根目录的路径("Web"路径)。(如果您的 PHP 安装是这样配置的,它们也可以在像 http://example.com/file.txt 这样的流上运行,但这在这里无关紧要)。

由于您的fopen()路径以 / 开头,文件系统会在文件系统的根目录中查找它。文件系统路径开头的/始终表示绝对路径而不是相对路径,并且目录结构实际上并不存在于该绝对位置。

您需要找到驻留在 Web 服务器文档根目录中的files/目录。从 uploads/ 目录中的 PHP 脚本访问它,您可以使用 .. 伪目录来执行此操作,这意味着"高一个目录",是获取同级目录的好方法。

$target_dir = "../files/" . usernameIs() . "/";

以上结果为相对路径。您可以将其包装在 realpath() 中以将其展开为完整路径。

不过,我会更频繁地使用 __DIR__ 常量来获取当前文件的目录,然后遍历..

$target_dir = __DIR__ . "/../files/" . usernameIs() . "/";

最后,$_SERVER['DOCUMENT_ROOT']也是一种选择。在您的情况下,files/位于 Web 服务器文档根目录内,因此您还可以使用:

$target_dir = $_SERVER['DOCUMENT_ROOT'] . "/files/" . usernameIs() . "/";

您还可以考虑定义一个常量来保留应用程序的文件系统根目录,您可以在执行include/require等时引用该常量。

define("APPLICATION_ROOT", '/home/u875642593/public_html');

不过,在您的确切情况下并没有太多好处,因为您的项目已经在文档根目录下。如果您需要将其移动到其他目录,例如如果您在 /home/u875642593/public_html/dev 中保留了开发版本,它确实会有所帮助。