使用PHP,给定URL,我如何确定它是否是图像?
URL没有上下文 - 它只是在纯文本文件的中间,或者可能只是一个字符串.
我不希望高开销(例如,读取URL的内容),因为可以在页面上调用许多URL.鉴于这种限制,所有图像都不是必需的,但我想要一个相当不错的猜测.
目前我只是在查看文件扩展名,但感觉应该有比这更好的方法.
这是我目前拥有的:
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;
}
Run Code Online (Sandbox Code Playgroud)
编辑:如果它对其他任何人有用,最后的功能是使用Emil H的答案:
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;
}
Run Code Online (Sandbox Code Playgroud)
Emi*_*l H 28
您可以使用HTTP HEAD请求并检查内容类型.这可能是一个很好的妥协.它可以使用PHP Streams完成.Wez Furlong有一篇文章展示了如何使用这种方法发送帖子请求,但它可以很容易地适应发送HEAD请求.您可以使用stream_get_meta_data()从http响应中检索标头.
当然这不是100%.有些服务器发送错误的标头 但是,它将处理通过脚本传送图像并且没有正确的文件扩展名的情况.真正确定的唯一方法是实际检索图像 - 全部或者前几个字节,如thomasrutter所建议的那样.
Ped*_*res 14
if(is_array(getimagesize($urlImg)))
echo 'Yes it is an image!';
Run Code Online (Sandbox Code Playgroud)
tho*_*ter 13
有几种不同的方法.
通过在文件开头查找幻数来嗅探内容.例如,GIF使用GIF87或GIF89作为文件的前五个字节(在ascii中).不幸的是,如果图像中存在错误或图像包含恶意内容,则无法告诉您.以下是各种类型图像文件的幻数(可随意使用):
"\xff\xd8\xff" => 'image/jpeg', "\x89PNG\x0d\x0a\x1a\x0a" => 'image/png', "II*\x00" => 'image/tiff', "MM\x00*" => 'image/tiff', "\x00\x00\x01\x00" => 'image/ico', "\x00\x00\x02\x00" => 'image/ico', "GIF89a" => 'image/gif', "GIF87a" => 'image/gif', "BM" => 'image/bmp',
嗅探这样的内容可能最符合您的要求; 你只需要阅读并因此下载文件的前几个字节(通过标题).
使用GD库加载图像以查看它是否加载而没有错误.这可以告诉您图像是否有效,没有错误.不幸的是,这可能不符合您的要求,因为它需要下载完整的图像.
不幸的是,文件既可以是有效图像,也可以是包含有害内容的ZIP文件,可以由有害网站作为Java执行 - 请参阅GIFAR漏洞.您几乎可以肯定通过将图像加载到像GD这样的库中并对其执行一些非平凡的过滤器来防止此漏洞,例如软化或锐化它(即使用卷积滤镜)并将其保存到新文件而不传输任何元数据.
试图通过单独的内容类型确定某些内容是否是图像是非常不可靠的,几乎与检查文件扩展名一样不可靠.使用<img元素加载图像时,浏览器会嗅探魔术字符串.
Raf*_*shi 10
除了Emil H的回答:
使用get_headers()来检查URL的内容类型,而无需下载整个文件,getimagesize()
$url_headers=get_headers($url, 1);
if(isset($url_headers['Content-Type'])){
$type=strtolower($url_headers['Content-Type']);
$valid_image_type=array();
$valid_image_type['image/png']='';
$valid_image_type['image/jpg']='';
$valid_image_type['image/jpeg']='';
$valid_image_type['image/jpe']='';
$valid_image_type['image/gif']='';
$valid_image_type['image/tif']='';
$valid_image_type['image/tiff']='';
$valid_image_type['image/svg']='';
$valid_image_type['image/ico']='';
$valid_image_type['image/icon']='';
$valid_image_type['image/x-icon']='';
if(isset($valid_image_type[$type])){
//do something
}
}
Run Code Online (Sandbox Code Playgroud)
编辑:适用于具有常用图像扩展名的静态图像
<?php
$imgExts = array("gif", "jpg", "jpeg", "png", "tiff", "tif");
$url ='path/to/image.png';
$urlExt = pathinfo($url, PATHINFO_EXTENSION);
if (in_array($urlExt, $imgExts)) {
echo 'Yes, '.$url.' is an Image';
}
?>
Run Code Online (Sandbox Code Playgroud)