如何使用 PHP 检查远程文件是否存在?
我能找到的最好的,一个 if
fclose
fopen
类型的东西,使得页面加载非常慢。
基本上我想做的是:我有一个网站列表,我想在它们旁边显示它们的图标。 但是,如果网站没有,我想用另一张图像替换它,而不是显示损坏的图像。
The best I could find, an if
fclose
fopen
type thing, makes the page load really slowly.
Basically what I'm trying to do is the following: I have a list of websites, and I want to display their favicons next to them. However, if a site doesn't have one, I'd like to replace it with another image rather than display a broken image.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(24)
您可以通过 CURLOPT_NOBODY 指示curl 使用HTTP HEAD 方法。
或多或少
无论如何,你只节省了HTTP传输的成本,而不是TCP连接建立和关闭的成本。 由于网站图标很小,您可能看不到太大的改进。
如果结果太慢,在本地缓存结果似乎是个好主意。
HEAD 检查文件的时间,并将其返回到标头中。 你可以像浏览器一样获取图标的CURLINFO_FILETIME。
您可以在缓存中存储 URL => [ 网站图标、时间戳 ]。 然后您可以比较时间戳并重新加载图标。
You can instruct curl to use the HTTP HEAD method via CURLOPT_NOBODY.
More or less
Anyway, you only save the cost of the HTTP transfer, not the TCP connection establishment and closing. And being favicons small, you might not see much improvement.
Caching the result locally seems a good idea if it turns out to be too slow.
HEAD checks the time of the file, and returns it in the headers. You can do like browsers and get the CURLINFO_FILETIME of the icon.
In your cache you can store the URL => [ favicon, timestamp ]. You can then compare the timestamp and reload the favicon.
正如 Pies 所说,您可以使用 cURL。 您可以让 cURL 只提供标题,而不提供正文,这可能会使其速度更快。 坏域名可能总是需要一段时间,因为您将等待请求超时; 您可以使用 cURL 更改超时长度。
这是示例:
As Pies say you can use cURL. You can get cURL to only give you the headers, and not the body, which might make it faster. A bad domain could always take a while because you will be waiting for the request to time-out; you could probably change the timeout length using cURL.
Here is example:
CoolGoose 的解决方案很好,但对于大文件来说速度更快(因为它只尝试读取 1 个字节):
CoolGoose's solution is good but this is faster for large files (as it only tries to read 1 byte):
这不是对您最初问题的答案,而是一种更好的方法来完成您想要做的事情:
而不是实际尝试直接获取网站的图标(这是一个巨大的痛苦,因为它可能是 /favicon.png,/ favicon.ico、/favicon.gif,甚至 /path/to/favicon.png),使用 google:
完成。
This is not an answer to your original question, but a better way of doing what you're trying to do:
Instead of actually trying to get the site's favicon directly (which is a royal pain given it could be /favicon.png, /favicon.ico, /favicon.gif, or even /path/to/favicon.png), use google:
Done.
得票最多的答案的完整功能:
您可以这样使用它:
A complete function of the most voted answer:
You can use it like this:
如果您正在处理图像,请使用 getimagesize。 与 file_exists 不同,此内置函数支持远程文件。 它将返回一个包含图像信息(宽度、高度、类型等)的数组。 您所要做的就是检查数组中的第一个元素(宽度)。 使用 print_r 输出数组的内容
If you are dealing with images, use getimagesize. Unlike file_exists, this built-in function supports remote files. It will return an array that contains the image information (width, height, type..etc). All you have to do is to check the first element in the array (the width). use print_r to output the content of the array
如果出于安全原因将 allow_url_fopen 设置设置为关闭,PHP 的内置函数可能无法检查 URL。 Curl 是一个更好的选择,因为我们以后不需要更改代码阶段。 下面是我用来验证有效 URL 的代码:
请注意 CURLOPT_SSL_VERIFYPEER 选项,该选项还验证 URL 是否以 HTTPS 开头。
PHP's inbuilt functions may not work for checking URL if allow_url_fopen setting is set to off for security reasons. Curl is a better option as we would not need to change our code at later stage. Below is the code I used to verify a valid URL:
Kindly note the CURLOPT_SSL_VERIFYPEER option which also verify the URL's starting with HTTPS.
应该管用 ;)
Should work ;)
这可以通过获取 HTTP 状态代码(404 = 未找到)来完成,可以使用
file_get_contents
文档使用上下文选项。 以下代码考虑了重定向,并将返回最终目的地的状态代码(演示):如果您不这样做想要跟随重定向,你可以这样做类似(演示):
解释了一些正在使用的函数、选项和变量我写的博客文章中有更多详细信息: HEAD First with PHP Streams 。
This can be done by obtaining the HTTP Status code (404 = not found) which is possible with
file_get_contents
Docs making use of context options. The following code takes redirects into account and will return the status code of the final destination (Demo):If you don't want to follow redirects, you can do it similar (Demo):
Some of the functions, options and variables in use are explained with more detail on a blog post I've written: HEAD first with PHP Streams.
要检查图像是否存在,
exif_imagetype
应该优于getimagesize
,因为它更快。要抑制
E_NOTICE
,只需在前面添加错误控制运算符 (@
)。作为奖励,通过
exif_imagetype
返回的值 (IMAGETYPE_XXX
),我们还可以通过image_type_to_mime_type
/ < 获取 mime 类型或文件扩展名代码>image_type_to_extension。To check for the existence of images,
exif_imagetype
should be preferred overgetimagesize
, as it is much faster.To suppress the
E_NOTICE
, just prepend the error control operator (@
).As a bonus, with the returned value (
IMAGETYPE_XXX
) fromexif_imagetype
we could also get the mime-type or file-extension withimage_type_to_mime_type
/image_type_to_extension
.一个彻底的解决方案是将图标显示为默认图标上方 div 中的背景图像。 这样,所有开销都将放在客户端上,同时仍然不会显示损坏的图像(据我所知,所有浏览器都会忽略缺少的背景图像)。
A radical solution would be to display the favicons as background images in a div above your default icon. That way, all overhead would be placed on the client while still not displaying broken images (missing background images are ignored in all browsers AFAIK).
您可以使用以下内容:
在尝试检查 URL 上是否存在图像时为我工作
You could use the following:
Worked for me when trying to check if an image exists on the URL
这对我来说可以检查 PHP 中是否存在远程文件:
This works for me to check if a remote file exist in PHP:
您可以使用 :
You can use :
如果您使用 Laravel 框架或 guzzle 包,还有一种使用 guzzle 客户端的更简单的方法,它在链接重定向时也可以工作:
文档中的更多内容: https://docs.guzzlephp.org/en/latest/faq.html#how-can- i-track-redirected-requests
If you're using the Laravel framework or guzzle package, there is also a much simpler way using the guzzle client, it also works when links are redirected:
More in Document : https://docs.guzzlephp.org/en/latest/faq.html#how-can-i-track-redirected-requests
您应该发出 HEAD 请求,而不是 GET 请求,因为您根本不需要 URI 内容。 正如 Pies 上面所说,您应该检查状态代码(在 200-299 范围内,并且您可以选择遵循 3xx 重定向)。
答案问题包含很多可能有用的代码示例:PHP / Curl:HEAD 请求在某些网站上需要很长时间
You should issue HEAD requests, not GET one, because you don't need the URI contents at all. As Pies said above, you should check for status code (in 200-299 ranges, and you may optionally follow 3xx redirects).
The answers question contain a lot of code examples which may be helpful: PHP / Curl: HEAD Request takes a long time on some sites
还有一个更复杂的替代方案。 您可以使用 JQuery 技巧来检查所有客户端。
来自 http://snipplr.com/ view/18782/add-a-favicon-near-external-links-with-jquery/(原始博客目前已关闭)
There's an even more sophisticated alternative. You can do the checking all client-side using a JQuery trick.
From http://snipplr.com/view/18782/add-a-favicon-near-external-links-with-jquery/ (the original blog is presently down)
这里所有使用 get_headers() 的答案都在执行 GET 请求。
仅执行 HEAD 请求会更快/更便宜。
为了确保 get_headers() 执行 HEAD 请求而不是 GET,您应该添加以下内容:
因此,要检查文件是否存在,您的代码将如下所示:
$file_found 显然将返回 false 或 true。
all the answers here that use get_headers() are doing a GET request.
It's much faster/cheaper to just do a HEAD request.
To make sure that get_headers() does a HEAD request instead of a GET you should add this:
so to check if a file exists, your code would look something like this:
$file_found will return either false or true, obviously.
如果文件不是外部托管的,您可以将远程 URL 转换为网络服务器上的绝对路径。 这样你就不必调用 CURL 或 file_get_contents 等。
If the file is not hosted external you might translate the remote URL to an absolute Path on your webserver. That way you don't have to call CURL or file_get_contents, etc.
不知道当文件远程不存在时这个是否更快,is_file(),但你可以尝试一下。
Don't know if this one is any faster when the file does not exist remotely, is_file(), but you could give it a shot.
如果您使用 Symfony 框架,还有一种使用 HttpClientInterface 的更简单方法:
HttpClient 的文档也非常好,如果您需要更具体的方法,也许值得研究一下:< a href="https://symfony.com/doc/current/http_client.html" rel="nofollow noreferrer">https://symfony.com/doc/current/http_client.html
If you're using the Symfony framework, there is also a much simpler way using the
HttpClientInterface
:The docs for the HttpClient are also very good and maybe worth looking into if you need a more specific approach: https://symfony.com/doc/current/http_client.html
您可以使用文件系统:
使用 Symfony\Component\Filesystem\Filesystem;
使用 Symfony\Component\Filesystem\Exception\IOExceptionInterface;
并检查
$fileSystem = 新文件系统();
if ($fileSystem->exists('path_to_file')==true) {...
You can use the filesystem:
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Filesystem\Exception\IOExceptionInterface;
and check
$fileSystem = new Filesystem();
if ($fileSystem->exists('path_to_file')==true) {...
请检查此网址。 我相信它会对你有所帮助。 他们提供了两种方法来克服这个问题并进行了一些解释。
试试这个。
或访问 URL
https://www.codexworld.com/how-to/check-if-remote-file-exists-url-php/# :~:text=%20file_exists()%20function%20in,a%20remote%20server%20using%20PHP。
Please check this URL. I believe it will help you. They provide two ways to overcome this with a bit of explanation.
Try this one.
or visit the URL
https://www.codexworld.com/how-to/check-if-remote-file-exists-url-php/#:~:text=The%20file_exists()%20function%20in,a%20remote%20server%20using%20PHP.