如何确定一个URL是否为图片?

4
我希望从语法上知道一个URL是否是图片。 例如:http://www.blah.com/plo52.jpg或png或gif将返回true。 如果URL以其他扩展名结尾,则该函数将返回false。
谢谢。

17
扩展程序不会告诉你这到底是不是一张图片。 - Ignacio Vazquez-Abrams
8个回答

14

检查文件的MIME类型。


1
但这需要获取文件。OP想知道从语法上是否是图像。无论如何,你的答案当然是正确的。 - Felix Kling
你是对的。我的错。无论如何, '/\.(png|jpg|gif|bmp)$/i' 也不是一个好(安全)的方式,但它当然更快,更容易。 - kjagiello
5
你可以只发送一个HEAD请求。 - Ignacio Vazquez-Abrams

8

这并不能告诉你它是否真的是一张图片。这只能告诉你根据URL它看起来像是一张图片:

$url = "http://somedomain.com/images/kittens.jpg";
if(preg_match("/\.(png|jpeg|jpg|gif|bmp)$/i", $url)) {
  print "Appears to be an image";
} else {
  print "Not an image.";
}

输出:

    看起来是一张图片

请注意,如果您希望看到通过.php脚本或.aspx脚本传递的图像,则此方法将失败。要进行真正可靠的测试,您需要检查mime类型。


1
有时候你需要实现一些简单而有效的东西,检查 MIME 类型可能很好,但在我看来有点过度设计了。+1 - JL.
许多图像托管网站为以图像文件扩展名结尾的URL提供HTML页面。 - Ben James
如果使用if(preg_match('/\.(png|jpg|gif|bmp)$/i', $url))语句,则可以实现此功能,因为preg_match函数当匹配不成功时会返回0(即False),反之则返回1,所以无需检查$matches变量。你忘记在表达式周围加上引号,并且我建议在表达式的开头加上\.,这样就不会匹配例如foo.apng的情况了。+1 - Felix Kling

5

我建议进行HTTP HEAD请求,这样就不需要下载整个图像。然后根据返回的字符串解析并确保Content-Type是image/jpegimage/pjpegimage/gifimage/png或类似的图像内容类型。

<?php

function parseImage( $url ) {
        $ch = curl_init();

    curl_setopt( $ch, CURLOPT_URL, $url );
    curl_setopt( $ch, CURLOPT_CONNECTTIMEOUT, 20 );
    curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 );

    curl_setopt( $ch, CURLOPT_HEADER, true );
    curl_setopt( $ch, CURLOPT_NOBODY, true );

    $content = curl_exec( $ch );

    var_dump($content);
    curl_close($ch);
}

parseImage('http://sstatic.net/so/img/logo.png');

返回结果:

字符串“HTTP/1.1 200 OK

Cache-Control:max-age=604800

Content-Length:3438

Content-Type:image/png

Last-Modified:Sun,10 Jan 2010 09:14:52 GMT

Accept-Ranges:bytes

ETag:“32741b5ed591ca1:0”

Server:Microsoft-IIS/7.5

Date:Wed,13 Jan 2010 20:37:47 GMT

'(长度=256)

Content-Type标题可以被篡改,但99%的情况下不会被篡改,这就是为什么该方法可靠的原因。


1
响应中的内容类型可以被伪造。 - kjagiello

3

非图片URL仍然可以返回图像。例如,ashx或asp URL可以返回图像数据。最好的方法是检查MIME类型,即Response.ContentType。


我点了赞,但是响应中的内容类型甚至可以被伪造或者错误。 - cjstehno

2

如果你真的需要100%确定,你需要下载资源并使用getimagesize()进行检查。


这正是我所想的,但他想要语法检查。不过还是点个赞。 - Aif

1

您可以使用pathinfo来获取扩展名:

echo pathinfo('http://www.blah.com/plo52.jpg', PATHINFO_EXTENSION); // jpg

然后将其包装到一个函数中

function hasExtension($uri, array $extensions = array('jpg','gif','png'))
{
    return in_array(pathinfo($uri, PATHINFO_EXTENSION), $extensions);
}

hasExtension('http://www.blah.com/plo52.jpg'); // true

这也适用于常规文件路径,并且通过能够传递$extension数组,您不受正则表达式模式的限制。请注意,该函数区分大小写。
请参阅此问题和答案以了解如何最佳确定文件的MimeType:how to best determine the MimeType of a file

1

我赞同 preg 的解决方案,但如果你真的、真的想知道,那么就下载文件并使用系统函数进行询问(例如,对于 Linux,请通过 exec 使用 file)。


1

你可能是指 get_headers()header_list 返回从你的服务器发送出去的头信息。 - Gordon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接