我想检查上传的文件是否为图像文件(例如png、jpg、jpeg、gif、bmp),或者是其他类型的文件。问题在于我正在使用Uploadify上传文件,这会更改MIME类型,并给出“text/octal”或某些东西作为MIME类型,无论您上传哪种文件。
除了使用PHP检查文件扩展名之外,是否有一种方法可以检查上传的文件是否为图像文件?
我想检查上传的文件是否为图像文件(例如png、jpg、jpeg、gif、bmp),或者是其他类型的文件。问题在于我正在使用Uploadify上传文件,这会更改MIME类型,并给出“text/octal”或某些东西作为MIME类型,无论您上传哪种文件。
除了使用PHP检查文件扩展名之外,是否有一种方法可以检查上传的文件是否为图像文件?
对于这个主题,我的想法很简单:所有上传的图片都是邪恶的。
不仅仅是因为它们可能包含恶意代码,更重要的是因为元标签。我知道有一些网络爬虫会浏览网页,使用隐藏的元标签来查找一些受保护的图片,然后侵犯它们的版权。也许有点偏执,但由于用户上传的图片在版权问题上无法控制,我认为这是一个严肃的问题。
为了解决这些问题,我系统地使用gd将所有上传的图片转换为png格式。这样做有很多优点:图片不会包含任何恶意代码和元标签,我只需要一种格式来处理所有上传的图片,我可以调整图片的大小以适应我的标准,而且...我可以立即知道图片是否有效!如果图片无法打开进行转换(使用imagecreatefromstring,它不关心图片格式),那么我就认为这张图片是无效的。
一个简单的实现可能是这样的:
function imageUploaded($source, $target)
{
// check for image size (see @DaveRandom's comment)
$size = getimagesize($source);
if ($size === false) {
throw new Exception("{$source}: Invalid image.");
}
if ($size[0] > 2000 || $size[1] > 2000) {
throw new Exception("{$source}: Too large.");
}
// loads it and convert it to png
$sourceImg = @imagecreatefromstring(@file_get_contents($source));
if ($sourceImg === false) {
throw new Exception("{$source}: Invalid image.");
}
$width = imagesx($sourceImg);
$height = imagesy($sourceImg);
$targetImg = imagecreatetruecolor($width, $height);
imagecopy($targetImg, $sourceImg, 0, 0, 0, 0, $width, $height);
imagedestroy($sourceImg);
imagepng($targetImg, $target);
imagedestroy($targetImg);
}
header('Content-type: image/png');
imageUploaded('http://www.dogsdata.com/wp-content/uploads/2012/03/Companion-Yellow-dog.jpg', 'php://output');
您可以使用getimagesize()
,对于非图像文件,它将返回大小为零的值。
exif_imagetype()
显然更快。 - rybo111/**
* Returns the image mime-type based on the first 6 bytes of a file
* It defaults to "application/octet-stream".
* It returns false, if problem with file or empty file.
*
* @param string $file
* @return string Mime-Type
*/
function isImage($file)
{
$fh = fopen($file,'rb');
if ($fh) {
$bytes = fread($fh, 6); // read 6 bytes
fclose($fh); // close file
if ($bytes === false) { // bytes there?
return false;
}
// ok, bytes there, lets compare....
if (substr($bytes,0,3) == "\xff\xd8\xff") {
return 'image/jpeg';
}
if ($bytes == "\x89PNG\x0d\x0a") {
return 'image/png';
}
if ($bytes == "GIF87a" or $bytes == "GIF89a") {
return 'image/gif';
}
return 'application/octet-stream';
}
return false;
}
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mimetype = finfo_file($finfo, $filename); //should contain mime-type
finfo_close($finfo);
imagecreatefromstring()
存在风险,因为攻击者可能通过少量请求使服务器内存被填满而导致DoS攻击。与其从任意数据字符串创建整个图像资源(每像素4个字节,一个RGBa位图),不如首先使用已经在接受答案中提到的getimagesize()
来确保图像格式可读并且尺寸合理。 - DaveRandom