best way to determine if a URL is an image in PHP
Using PHP, given a URL, how can I determine whether it is an image?
There is no context for the URL - it is just in the middle of a plain text file, or maybe just a string on its own.
I don't want high overhead (e.g. reading the content of the URL) as this could be called for many URLs on a page. Given this restriction, it isn't essential that all images are identified, but I would like a fairly good guess.
At the moment I am just looking at the file extension, but it feels like there should be a better way than this.
Here is what I currently have:
function isImage( $url )
{
$pos = strrpos( $url, ".");
if ($pos === false)
return false;
$ext = strtolower(trim(substr( $url, $pos)));
$imgExts = array(".gif", ".jpg", ".jpeg", ".png", ".tiff", ".tif"); // this is far from complete but that's always going to be the case...
if ( in_array($ext, $imgExts) )
return true;
return false;
}
Edit: In case it's useful to anybody else here is the final function using the technique from Emil H's answer:
function isImage($url)
{
$params = array('http' => array(
'method' => 'HEAD'
));
$ctx = stream_context_create($params);
$fp = @fopen($url, 'rb', false, $ctx);
if (!$fp)
return false; // Problem with url
$meta = stream_get_meta_data($fp);
if ($meta === false)
{
fclose($fp);
return false; // Problem reading data from url
}
$wrapper_data = $meta["wrapper_data"];
if(is_array($wrapper_data)){
foreach(array_keys($wrapper_data) as $hh){
if (substr($wrapper_data[$hh], 0, 19) == "Content-Type: image") // strlen("Content-Type: image") == 19
{
fclose($fp);
return true;
}
}
}
fclose($fp);
return false;
}
You could use an HTTP HEAD request and check the content-type. This might be a good compromise. It can be done using PHP Streams. Wez Furlong has an article that shows how to use this approach to send post requests, but it can be easily adapted to send HEAD requests instead. You can retrieve the headers from an http response using stream_get_meta_data().
Of course this isn't really 100%. Some servers send incorrect headers. It will however handle cases where images are delivered through a script and the correct file extension isn't available. The only way to be really certain is to actually retrieve the image - either all of it, or the first few bytes, as suggested by thomasrutter.
if(is_array(getimagesize($urlImg)))
echo 'Yes it is an image!';