在PHP脚本,调用是否include()
,require()
,fopen()
,或它们的衍生物,例如include_once
,require_once
或者甚至move_uploaded_file()
,一个经常遇到错误或警告:
无法打开流:没有这样的文件或目录。
有什么好的方法可以快速找到问题的根本原因?
有很多原因可能会导致此错误,因此对要首先检查的内容进行检查的清单非常有帮助。
让我们考虑对以下行进行故障排除:
require "/path/to/file"
或将由require*
或调用的任何内容include*
移至其自己的变量,将其回显,复制并尝试从终端访问它:
$path = "/path/to/file";
echo “Path : $path”;
require “$path”;
然后,在终端中:
cat <file path pasted>
/users/tony/htdocs
最佳做法:
为了使脚本健壮,以防万一,您仍然可以在运行时生成绝对路径,但有两个选择:
require __DIR__ . "/relative/path/from/current/file"
。该__DIR__
幻常量返回当前文件的目录。SITE_ROOT
自己定义一个常量:
config.php
在中config.php
,写
define('SITE_ROOT', __DIR__);
在要引用站点根文件夹的每个文件中,包括config.php
,然后在需要的SITE_ROOT
地方使用常量:
require_once __DIR__."/../config.php";
…
require_once SITE_ROOT.”/other/file.php”;
这两种做法还使您的应用程序更加可移植,因为它不依赖于ini设置(例如包含路径)。
既不是相对也不是绝对的,包含文件的另一种方法是依靠include路径。对于库或框架(例如Zend框架),通常是这种情况。
这样的包含将如下所示:
include "Zend/Mail/Protocol/Imap.php"
在这种情况下,您将要确保“ Zend”所在的文件夹是包含路径的一部分。
您可以使用以下命令检查包含路径:
echo get_include_path();
您可以使用添加一个文件夹:
set_include_path(get_include_path().":"."/path/to/new/folder");
可能总的来说,运行服务器进程(Apache或PHP)的用户根本没有读取或写入该文件的权限。
要检查服务器在哪个用户下运行,可以使用posix_getpwuid:
$user = posix_getpwuid(posix_geteuid());
var_dump($user);
要查找文件的权限,请在终端中键入以下命令:
ls -l <path/to/file>
并查看许可符号
如果以上方法均无效,则可能是某些PHP设置禁止其访问该文件。
三个设置可能是相关的:
phpinfo()
或使用来检查ini_get("open_basedir")
ini_get("allow_url_include")
并设置ini_set("allow_url_include", "1")
如果以上方法均无法诊断问题,则可能会发生一些特殊情况:
您可能会使用相对或绝对路径包含一个库,例如Zend框架。例如 :
require "/usr/share/php/libzend-framework-php/Zend/Mail/Protocol/Imap.php"
但是随后您仍然会遇到同样的错误。
发生这种情况的原因是,您已(成功)包含的文件本身具有另一个文件的include语句,而第二个include语句假定您已将该库的路径添加到include路径中。
例如,前面提到的Zend框架文件可以包含以下内容:
include "Zend/Mail/Protocol/Exception.php"
既不是相对路径也不是绝对路径。假定Zend框架目录已添加到包含路径。
在这种情况下,唯一可行的解决方案是将目录添加到包含路径。
如果运行的是增强安全性的Linux,则可能是该问题的原因,原因是拒绝从服务器访问文件。
要检查系统上是否启用 了 SELinux
,请sestatus
在终端中运行命令。如果该命令不存在,则SELinux不在您的系统上。如果确实存在,那么它应该告诉您是否强制执行。
要检查SELinux策略是否是 问题 的原因 ,您可以尝试暂时将其关闭。但是请小心,因为这将完全禁用保护。不要在生产服务器上执行此操作。
setenforce 0
如果您再也没有关闭SELinux的问题,那么这就是根本原因。
要解决此问题 ,您将必须相应地配置SELinux。
以下上下文类型将是必需的:
httpd_sys_content_t
用于您希望服务器能够读取的文件httpd_sys_rw_content_t
用于您要对其进行读写访问的文件httpd_log_t
用于日志文件httpd_cache_t
用于缓存目录例如,要将httpd_sys_content_t
上下文类型分配给您的网站根目录,请运行:
semanage fcontext -a -t httpd_sys_content_t "/path/to/root(/.*)?"
restorecon -Rv /path/to/root
如果文件位于主目录中,则还需要打开httpd_enable_homedirs
boolean:
setsebool -P httpd_enable_homedirs 1
无论如何,根据您的策略,SELinux可能会出于多种原因拒绝访问文件。因此,您需要对此进行调查。是专门针对Web服务器配置SELinux的教程。
如果您使用的是Symfony,并且在上载到服务器时遇到此错误,则可能是由于app/cache
上载或未清除该缓存而未重置该应用程序的缓存。
您可以通过运行以下控制台命令来测试和修复此问题:
cache:clear
显然,zip->close()
当zip中的某些文件的文件名中包含非ASCII字符(例如“é”)时,也会发生此错误。
潜在的解决方案是utf8_decode()
在创建目标文件之前将文件名包装在其中。
感谢Fran Cano提出并建议了此问题的解决方案
免责声明:在堆栈溢出中也有类似的问题,但这些问题是他们各自的答案,既不适合这个问题,也不帮助解决他们的答案。这些问题是不同的,答案只适合那些具体的问题,而不是通用的。经过长时间的挣扎,他们没有任何帮助,我想了两次我要发布这个问题来寻求帮助。如果有人不喜欢这个问题或不理解,请沟通并得到澄清,而不是勉强设置标志来关闭这个问题;最好你可以忽略并传递...谢谢你! 需求:我使用Zend框架的谷歌日历API
我正在尝试让PHP将上传的文件从tmp目录移动到Web服务器上的永久位置。这看起来很简单,但我遇到了这个错误: 很直接,对吧?它找不到目标文件夹。 我的问题是:如何引用所需的目标目录? 引用是相对于脚本在服务器上的位置?还是相对于URL?还是?还是操作系统的文件系统?还是其他东西? 我在PHP文档中找不到答案,甚至在SO上的任何类似问题中也找不到答案.. 有人能帮忙吗?谢谢
我正在按照教程将图片从android上传到服务器,我在服务器端使用php,这是代码: 当我尝试运行时,它会向我显示以下错误: fopen(uploadedimages/):无法打开流:中没有这样的文件或目录... fwrite()期望参数1为资源,布尔值在…fclose()中给定期望参数1是资源,布尔函数在…中给定。。。 我对php非常陌生,所以请帮助我(我从互联网上找到了一些答案,但它不适合我)
我正在使用Codeignighter,FPDF和FPDI来修改要通过电子邮件发送给客户的PDF。 使用FPDI给出的基本示例,我可以让我的代码在localhost上完美工作(独立的php文件,没有代码签名器),但是当我将相同的文件放到服务器上时,我会收到以下警告和错误。 严重性:警告 消息:fopen(PDF.pdf):无法打开流:没有这样的文件或目录 文件名: pdfParser/StreamR
我包含这样的PHP类 但是当我执行代码时,出现了一个错误 警告:require_once(C:\xampp\htdocs\xampp\htdocs\aclass\classfile.php):无法打开流:第 2 行的 C:\xampp\htdocs\aclass\index.php 中没有此类文件或目录 致命错误:require_once():需要打开失败 第 2 行的 C:\xampp.php\
错误:警告:require_once(…/tcpdf/config/lang):无法打开流:在第33行的C:\xampp\htdocs\jmb_system\anggerik\printunitstmt.php中没有这样的文件或目录 致命错误:require_once():失败打开需要'…/tcpdf/config/lang'(include_path='.; C:\xampp\php\PEAR'