如何使用PHP检查是否存在远程文件?

83 php testing networking file

我能找到的最好的,if fclose fopen类型的东西,使页面加载非常缓慢.

基本上我要做的是以下内容:我有一个网站列表,我想在他们旁边显示他们的favicon.但是,如果一个站点没有,我想用另一个图像替换它而不是显示损坏的图像.

Ram*_*oca 131

您可以通过CURLOPT_NOBODY指示curl使用HTTP HEAD方法.

或多或少

$ch = curl_init("http://www.example.com/favicon.ico");

curl_setopt($ch, CURLOPT_NOBODY, true);
curl_exec($ch);
$retcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
// $retcode >= 400 -> not found, $retcode = 200, found.
curl_close($ch);
Run Code Online (Sandbox Code Playgroud)

无论如何,您只能节省HTTP传输的成本,而不是TCP连接的建立和关闭.而对于小的优惠,你可能看不到多少改进.

如果结果太慢,那么在本地缓存结果似乎是一个好主意.HEAD检查文件的时间,并在标题中返回.您可以像浏览器一样获取图标的CURLINFO_FILETIME.在缓存中,您可以存储URL => [favicon,timestamp].然后,您可以比较时间戳并重新加载favicon.

  • 只是注意:所有400个代码上的`retcode`错误,所以验证将是`> =`而不仅仅是`>` (6认同)
  • @Lyth 3XX retcodes不是错误,而是重定向.这些应该手动处理或使用CURLOPT_FOLLOWLOCATION处理. (6认同)
  • 使用curl_setopt($ ch,CURLOPT_SSL_VERIFYPEER,false); 同时确保相同的代码适用于以HTTPS开头的URL! (6认同)
  • 有些网站禁止访问,如果你不提供用户代理字符串,所以我建议您按照本指南除了CURLOPT_NOBODY添加CURLOPT_USERAGENT:http://davidwalsh.name/set-user-agent-php-curl-spoof (4认同)

Tom*_*igh 60

正如派斯所说,你可以使用cURL.你可以得到cURL只给你标题,而不是身体,这可能会使它更快.糟糕的域名可能总是需要一段时间,因为您将等待请求超时; 您可以使用cURL更改超时长度.

这是一个例子:

function remoteFileExists($url) {
    $curl = curl_init($url);

    //don't fetch the actual page, you only want to check the connection is ok
    curl_setopt($curl, CURLOPT_NOBODY, true);

    //do request
    $result = curl_exec($curl);

    $ret = false;

    //if request did not fail
    if ($result !== false) {
        //if request was ok, check response code
        $statusCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);  

        if ($statusCode == 200) {
            $ret = true;   
        }
    }

    curl_close($curl);

    return $ret;
}

$exists = remoteFileExists('http://stackoverflow.com/favicon.ico');
if ($exists) {
    echo 'file exists';
} else {
    echo 'file does not exist';   
}
Run Code Online (Sandbox Code Playgroud)

  • remoteFileExists('http://stackoverflow.com/')这也会返回true,但它只是一个链接.此功能不检查是链接内容类型是文件. (3认同)

小智 34

CoolGoose的解决方案很好,但对于大文件来说速度更快(因为它只尝试读取1个字节):

if (false === file_get_contents("http://example.com/path/to/image",0,null,0,1)) {
    $image = $default_image;
}
Run Code Online (Sandbox Code Playgroud)

  • 你可以只使用“fopen” - 如果请求返回代码是 404,fopen 返回 false。 (2认同)
  • 这真的很慢并且对我不起作用(这意味着如果文件路径不正确它仍然显示损坏的图像) (2认同)

Mal*_*ala 27

这不是您原始问题的答案,而是您尝试做的更好的方式:

而不是直接尝试直接获取网站的favicon(这可能是一个皇家的痛苦,因为它可能是/favicon.png,/ favicon.ico,/ favicon.gif,甚至/path/to/favicon.png),使用谷歌:

<img src="http://www.google.com/s2/favicons?domain=[domain]">
Run Code Online (Sandbox Code Playgroud)

完成.

  • 语法有点混乱.所以这里有一个例子:<img rel="nofollow noreferrer" src ="http://www.google.com/s2/favicons?domain=stackoverflow.com"> (4认同)

Эџa*_*мaи 18

如果您正在处理图像,请使用getimagesize.与file_exists不同,此内置函数支持远程文件.它将返回一个包含图像信息的数组(width,height,type..etc).您所要做的就是检查数组中的第一个元素(宽度).使用print_r输出数组的内容

$imageArray = getimagesize("http://www.example.com/image.jpg");
if($imageArray[0])
{
    echo "it's an image and here is the image's info<br>";
    print_r($imageArray);
}
else
{
    echo "invalid image";
}
Run Code Online (Sandbox Code Playgroud)


Ped*_*ito 15

最投票答案的完整功能:

function remote_file_exists($url)
{
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_NOBODY, true);
    curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);
    if( $httpCode == 200 ){return true;}
}
Run Code Online (Sandbox Code Playgroud)

你可以像这样使用它:

if(remote_file_exists($url))
{
    //file exists, do something
}
Run Code Online (Sandbox Code Playgroud)


hak*_*kre 7

这可以通过获取使用上下文选项的file_get_contentsDocs可能的HTTP状态代码(404 =未找到)来完成.以下代码将重定向考虑在内,并将返回最终目标(Demo)的状态代码:

$url = 'http://example.com/';
$code = FALSE;

$options['http'] = array(
    'method' => "HEAD",
    'ignore_errors' => 1
);

$body = file_get_contents($url, NULL, stream_context_create($options));

foreach($http_response_header as $header)
    sscanf($header, 'HTTP/%*d.%*d %d', $code);

echo "Status code: $code";
Run Code Online (Sandbox Code Playgroud)

如果您不想遵循重定向,则可以类似(演示):

$url = 'http://example.com/';
$code = FALSE;

$options['http'] = array(
    'method' => "HEAD",
    'ignore_errors' => 1,
    'max_redirects' => 0
);

$body = file_get_contents($url, NULL, stream_context_create($options));

sscanf($http_response_header[0], 'HTTP/%*d.%*d %d', $code);

echo "Status code: $code";
Run Code Online (Sandbox Code Playgroud)

在我写的博客文章中更详细地解释了一些正在使用的函数,选项和变量:HEAD首先使用PHP Streams.


Coo*_*ose 6

if (false === file_get_contents("http://example.com/path/to/image")) {
    $image = $default_image;
}
Run Code Online (Sandbox Code Playgroud)

应该管用 ;)


Kri*_*pal 6

如果出于安全原因将allow_url_fopen设置设置为off,则PHP的内置函数可能无法用于检查URL .Curl是一个更好的选择,因为我们不需要在后期更改我们的代码.以下是我用来验证有效网址的代码:

$url = str_replace(' ', '%20', $url);
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); 
curl_setopt($ch, CURLOPT_NOBODY, true);
curl_exec($ch);
$httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);  
curl_close($ch);
if($httpcode>=200 && $httpcode<300){  return true; } else { return false; } 
Run Code Online (Sandbox Code Playgroud)

请注意CURLOPT_SSL_VERIFYPEER选项,该选项还验证从HTTPS开始的URL.


yck*_*art 6

要检查图像是否存在,exif_imagetype应该优先于getimagesize,因为它要快得多。

要抑制E_NOTICE,只需添加错误控制运算符 ( @)。

if (@exif_imagetype($filename)) {
  // Image exist
}
Run Code Online (Sandbox Code Playgroud)

作为奖励,我们还可以通过返回值 ( IMAGETYPE_XXX)exif_imagetype获得带有image_type_to_mime_type/的 mime 类型或文件扩展名image_type_to_extension