file_exists 或 getimagesize 仅适用于本地、绝对文件路径,但不适用于 PHP 中的 URL

Posted

技术标签:

【中文标题】file_exists 或 getimagesize 仅适用于本地、绝对文件路径,但不适用于 PHP 中的 URL【英文标题】:file_exists or getimagesize only work with local, absolute file paths, but not with URLs in PHP 【发布时间】:2015-12-13 16:05:46 【问题描述】:

我最近更新了我的一台服务器,从那以后,我遇到了一些特定 php 命令的问题(见下文)。我相信这是一个配置问题,但我已经研究了一些事情并且不知道更多。所以也许你们中的一个人有一个好主意:

我使用以下代码在 Intranet 站点上显示标准徽标或用户定义的徽标:

if(L_HEADER) 
  $logo = L_HEADER;

else 
  $logo = 'logo.png';

$properties = getimagesize(CONFIG_URL . 'images/' . $logo)

L_HEADER 和 CONFIG_URL 是具有预定义值的常量(另一个文件):

    L_HEADER 包含“opb_beta.png” CONFIG_URL 包含“http://billing.intranet.opb/”

连接工作正常,Apache 日志文件的错误消息也证实了这一点:

PHP 警告:getimagesize(http://billing.intranet.opb/images/opb_beta.png):打开流失败:HTTP 请求失败! HTTP/1.1 404 未找到 在 /var/www/billing/templates/header.inc.php 第 42 行

所以第一个明显的结论是:路径是错误的。但事实并非如此,相信我。我检查了 1.000 次。事实上,第一个好奇心是图像在同一个文件的代码中的几行中正确显示和引用:

echo '<img src="' . CONFIG_URL . 'images/' . $logo . '"  
   height = "' . $properties[1] . '" />";

当我得到上面提到的错误时,高度和宽度是“0”,但是查看源代码,URL很好,手动访问它会打开图像,当用手动值替换宽度和高度时,图像是显示得很好。

更奇怪的是(以及我目前的 finx),将 getimagesize 更改为以下内容时,它工作得很好:

$properties = getimagesize($_SERVER['DOCUMENT_ROOT'] . /public_html/images/' . $logo);

我会提到我正在使用 Apache 的重定向;这就是为什么在 URL 中看不到“public_html”,而在第二个示例的绝对路径中却看到它。

“file_exists”也是如此。 URL 不起作用,同一文件的绝对本地路径起作用。

另一个好奇心:在另一段代码中,我正在在线检查更新。在那里,我使用带有 file_exists 和 fopen 的“真实”公共 URL。我看起来像这样并且工作得很好:

if(file_exists('http://desk.co.cr/df_stable.txt') 
  if(($handle = fopen('http://desk.co.cr/df_stable.txt', 'r')) !== FALSE) 
    // some other code
  

现在,我已经检查过的东西:

正确设置了整个路径的文件权限,www-data 是所有文件的组和所有者以及图像文件的读写权限 allow_url_fopen 设置为“开启”。 open_basedir 设置为“无值”,并且在 Apache 的虚拟主机定义中没有覆盖。 文件确实存在且语法+路径正确。

一些背景信息:

服务器在 Ubuntu 14.04 LTS 上运行 Apache 2.4.7 PHP 5.5.9

目前,我没有想法。

【问题讨论】:

您是否查看了 access_log 以查看真正请求的 url?也许你有一个不稳定的重写。 可能是服务器的主机文件?当您在服务器上为域执行 nslookup 时会发生什么? @MarcB 是的,我检查了 access_log 和 error_log。两者都显示正确的 URL。我什至将其复制并粘贴到浏览器中进行检查,图像显示正常。 @Blowski:您的评论与以下@IMSoP 的评论方向相同。事实上,为了将内网与任何其他“正常”网站区分开来,这里运行的是 dnsmasq。 nslookup显示nslookup billing.intranet.opbServer: 127.0.0.1Address: 127.0.0.1#53Name: billing.intranet.opbAddress: 158.120.100.152不要问为什么这个IP。这是我们 LAN 的本地 IP 地址 - 长篇大论 ;-) 【参考方案1】:

隐藏在你的问题中的是你已经发现的这条重要线索:

另一个好奇心:在另一段代码中,我正在在线检查更新。在那里,我使用的是“真实”的公共 URL

因此,失败的 URL 指向非公共域,您的 PC 已配置为查找正确的 IP 地址。这很可能是通过运行本地 DNS 服务器或配置 PC 的“主机”文件以硬编码该域的地址来完成的。

但是,当您从服务器本身请求 URL 时,一个完全不同的 DNS 配置正在发挥作用,因此它可能根本不知道该服务器在哪里 - 即使它是它自己!您需要配置服务器的 DNS 设置或 /etc/hosts 以匹配您 PC 上的内容。

一个相关的可能性是服务器配置了相同的地址查找,但路由器不允许它以这种方式连接到自己。解决此问题的一种方法是将主机文件条目指向 127.0.0.1 并将 Apache 配置为匹配。

如果您可以在服务器上获得命令行,您可以尝试:

nslookup billing.intranet.opb
# if that returns the right IP address, see if it's reachable:
ping billing.intranet.opb
# and if it's the right server, it will be listening on port 80:
telnet billing.intranet.opb 80
# telnet will either time out, or connect and give you a prompt

如果 telnet 连接,您甚至可以手动编写 HTTP 请求(空行完成请求;不要花太长时间输入,否则服务器会退出)例如:

HTTP/1.1 HEAD /
Host: billing.intranet.opb

【讨论】:

你是对的——这里运行着一个 dnsmasq,它负责处理什么请求出去,什么留在里面。不使用硬编码的“主机”文件。您对 的最后评论可能是一种可能性,但我不知道如何检查它。 @IMoSP 抱歉回复晚了,但我走了。首先感谢您的反馈。我执行了不同的命令,nslookup 返回了正确的 IP,ping 也是如此。 billing.intranet.opb 也可以通过telnet 获得,并且正确返回了标题(我尝试了普通的HTTPGET)。

以上是关于file_exists 或 getimagesize 仅适用于本地、绝对文件路径,但不适用于 PHP 中的 URL的主要内容,如果未能解决你的问题,请参考以下文章

file_exists 和包含相对路径的路径(“/../”)

file_exists 或 getimagesize 仅适用于本地、绝对文件路径,但不适用于 PHP 中的 URL

PHP 中的 file_exists 未按预期工作

is_file/file_exists 性能和缓存

PHP file_exists 目录

PHP file_exists 对现有文件返回 false