Correct PHP way to check if external image exists?

2020-05-23 08:03发布

I know that there are at least 10 the same questions with answers but none of them seems to work for me flawlessly. I'm trying to check if internal or external image exists (is image URL valid?).

  1. fopen($url, 'r') fails unless I use @fopen():

    Warning: fopen(http://example.com/img.jpg) [function.fopen]: failed to open stream: HTTP request failed! HTTP/1.1 404 Not Found in file.php on line 21
    
  2. getimagesize($img) fails when image doesn't exist (PHP 5.3.8):

    Warning: getimagesize() [function.getimagesize]: php_network_getaddresses: getaddrinfo failed
    
  3. CURL fails because it isn't supported by some servers (although it's present mostly everywhere).
  4. fileExists() fails because it doesn't work with external URLs and can't possibly check if we're dealing with image.

Four methods that are the most common answers to such question are wrong. What would be the correct way to do that?

标签: php image exists
9条回答
干净又极端
2楼-- · 2020-05-23 08:35
function checkExternalFile($url)
{
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_NOBODY, true);
    curl_exec($ch);
    $retCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    return $retCode;
}

$fileExists = checkExternalFile("http://example.com/your/url/here.jpg");

// $fileExists > 400 = not found
// $fileExists = 200 = found.
查看更多
地球回转人心会变
3楼-- · 2020-05-23 08:36

You can use the PEAR/HTTP_Request2 Package for this. You can find it here

Here comes an example. The Example expects that you have installed or downloaded the HTTP_Request2 package properly. It uses the old style socket adapter, not curl.

<?php

require_once 'HTTP/Request2.php';
require_once 'HTTP/Request2/Adapter/Socket.php';

$request = new HTTP_Request2 (
    $your_url, 
    HTTP_Request2::METHOD_GET,
    array('adapter' => new HTTP_Request2_Adapter_Socket())
);

switch($request->send()->getResponseCode()) {

    case 404 : 
        echo 'not found';
        break;

    case 200 :
        echo 'found';
        break;

    default :
        echo 'needs further attention';

}
查看更多
唯我独甜
4楼-- · 2020-05-23 08:38

Use fsockopen, connect to the server, send a HEAD request and see what status you get back.

The only time you need to be aware of problems is if the domain doesn't exist.

Example code:

$file = "http://example.com/img.jpg";
$path = parse_url($file);
$fp = @fsockopen($path['host'],$path['port']?:80);
if( !$fp) echo "Failed to connect... Either server is down or host doesn't exist.";
else {
  fputs($fp,"HEAD ".$file." HTTP/1.0\r\n"
     ."Host: ".$path['host']."\r\n\r\n");
  $firstline = fgets($fp);
  list(,$status,$statustext) = explode(" ",$firstline,3);
  if( $status == 200) echo "OK!";
  else "Status ".$status." ".$statustext."...";
}
查看更多
迷人小祖宗
5楼-- · 2020-05-23 08:38

I found try catch the best solution for this. It is working fine with me.

try{
      list($width, $height) = getimagesize($h_image->image_url);
   }
catch (Exception $e)
    {
    }
查看更多
小情绪 Triste *
6楼-- · 2020-05-23 08:40

There are multiple steps, there is no single solution:

  1. Validate URL
  2. Check whether the file is available (can be done directly with step 3)
  3. Download the image into a tmp file.
  4. Use getimagesize to check the size of the image.

For this kind of work you can catch the exceptions and handle them well to define your answer. In this case you could even suppress errors because it's intended that they trick might fail. So you handle the errors correctly.

Because it's not possible to do a 100% check on it without having the actual image downloaded. So step 1 and 2 are required, 3 and 4 optional for a more definitive answer.

查看更多
Ridiculous、
7楼-- · 2020-05-23 08:49

If you're using PHP >=5.0.0 you can pass an additional parameter into fopen to specify context options for HTTP, among them whether to ignore failure status codes.

$contextOptions = array( 'http' => array('ignore_errors' => true));

$context = stream_context_create($contextOptions);

$handle = fopen($url, 'r', false, $context);
查看更多
登录 后发表回答