我想验证我的上传文件是图像与否。在搜索之后,我找到了两种方式,我认为这是一种很好的方法。第一个代码是:
$whitelist_type = array('image/jpeg', 'image/png','image/gif');
$fileinfo = finfo_open(FILEINFO_MIME_TYPE);
if (!in_array(finfo_file($fileinfo, $file['tmp_name']), $whitelist_type)) {
$error[] = "Uploaded file is not a valid image";
}
和第二个代码:
if (!getimagesize($_FILES['photo']['tmp_name'])) {
$error[] = "Uploaded file is not a valid image";
}
哪个代码更可靠来检查它是一个图像,为什么?还是比这更好的方式?感谢。
答案 0 :(得分:4)
finfo_*
库会很好,但它适用于> = 5.3.0
个版本,
AND getimagesize()
GD
库函数,即返回图片信息WxH
和size
如果图片无效,则getimagesize()
显示警告,以便更好地使用finfo_*
函数验证图片,
您也可以使用跨版本代码,请参阅下面的示例代码
<?php
$file = $_FILES['photo'];
$whitelist_type = array('image/jpeg', 'image/png','image/gif');
$error = null;
if(function_exists('finfo_open')){ //(PHP >= 5.3.0, PECL fileinfo >= 0.1.0)
$fileinfo = finfo_open(FILEINFO_MIME_TYPE);
if (!in_array(finfo_file($fileinfo, $file['tmp_name']), $whitelist_type)) {
$error[] = "Uploaded file is not a valid image";
}
}else if(function_exists('mime_content_type')){ //supported (PHP 4 >= 4.3.0, PHP 5)
if (!in_array(mime_content_type($file['tmp_name']), $whitelist_type)) {
$error[] = "Uploaded file is not a valid image";
}
}else{
if (!@getimagesize($file['tmp_name'])) { //@ - for hide warning when image not valid
$error[] = "Uploaded file is not a valid image";
}
}
答案 1 :(得分:2)
为什么不使用exif_imagetype:
if (exif_imagetype($file['tmp_name']) != (IMAGETYPE_JPEG || IMAGETYPE_GIF || IMAGETYPE_PNG)) {
$error[] = "Uploaded file is not a valid image";
}
它可能会比其他任何一个都快。 (PHP 4&gt; = 4.3.0,PHP 5)
答案 2 :(得分:2)
从安全角度来看,您可能最好将上传的文件推测转换为图片,看看是否成功,并保留并提供转换后的结果在那里。
您可以根据您检测到的MIME类型,使用GD library中的imagecreatefrom...()
个功能之一,例如来自$_FILES
数组,和/或来自exif_imagetype()
,finfo_file()
等。
问题在于,有些漏洞假装是有效图像(在某些情况下是有效图像),但也是有效的JavaScript,Flash或其他可能运行的代码容器在某些情况下由客户的浏览器。
参见例如https://www.defcon.org/images/defcon-15/dc15-presentations/dc-15-schrenk.pdf
答案 3 :(得分:0)
我使用的最快方法是自定义PHP函数,该函数从文件读取特定字节。当检查文件很大(电影,iso图像等)时,它的工作速度比getimagesize
快得多。
fastImageGet('image.jpg'); // returns size and image type in array or false if not image
fastImageGet('image.jpg', 'type'); // returns image type only
fastImageGet('image.jpg', 'size'); // returns image size only
function fastImageGet($file, $what=null) {
if (!in_array($what, ['size', 'type']))
$what = null;
// INIT
$pos = 0; $str = null;
if (is_resource($file))
$fp = $file;
elseif (!@filesize($file))
return false;
else
try {
$fp = fopen($file, 'r', false);
} catch (\Exception $e) {
return false;
}
// HELPER FUNCTIONS
$getChars = function($n) use (&$fp, &$pos, &$str) {
$response = null;
if (($pos + $n - 1) >= strlen($str)) {
$end = $pos + $n;
while ((strlen($str) < $end) && ($response !== false)) {
$need = $end - ftell($fp);
if (false !== ($response = fread($fp, $need)))
$str .= $response;
else
return false;
}
}
$result = substr($str, $pos, $n);
$pos += $n;
return $result;
};
$getByte = function() use ($getChars) {
$c = $getChars(1);
$b = unpack('C', $c);
return reset($b);
};
$readInt = function ($str) {
$size = unpack('C*', $str);
return ($size[1] << 8) + $size[2];
};
// GET TYPE
$t2 = $getChars(2);
if ($t2 === 'BM')
$type = 'bmp';
elseif ($t2 === 'GI')
$type = 'gif';
elseif ($t2 === chr(0xFF) . chr(0xd8))
$type = 'jpeg';
elseif ($t2 === chr(0x89) . 'P')
$type = 'png';
else
$type = false;
if (($type === false) || ($what === 'type')) {
fclose($fp);
return $type;
}
// GET SIZE
$pos = 0;
if ($type === 'bmp') {
$chars = $getChars(29);
$chars = substr($chars, 14, 14);
$ctype = unpack('C', $chars);
$size = (reset($ctype) == 40)
? unpack('L*', substr($chars, 4))
: unpack('L*', substr($chars, 4, 8));
} elseif ($type === 'gif') {
$chars = $getChars(11);
$size = unpack('S*', substr($chars, 6, 4));
} elseif ($type === 'jpeg') {
$state = null;
while (true) {
switch ($state) {
default:
$getChars(2);
$state = 'started';
break;
case 'started':
$b = $getByte();
if ($b === false) {
$size = false;
break 2;
}
$state = $b == 0xFF ? 'sof' : 'started';
break;
case 'sof':
$b = $getByte();
if (in_array($b, range(0xE0, 0xEF)))
$state = 'skipframe';
elseif (in_array($b, array_merge(range(0xC0, 0xC3), range(0xC5, 0xC7), range(0xC9, 0xCB), range(0xCD, 0xCF))))
$state = 'readsize';
elseif ($b == 0xFF)
$state = 'sof';
else
$state = 'skipframe';
break;
case 'skipframe':
$skip = $readInt($getChars(2)) - 2;
$state = 'doskip';
break;
case 'doskip':
$getChars($skip);
$state = 'started';
break;
case 'readsize':
$c = $getChars(7);
$size = [$readInt(substr($c, 5, 2)), $readInt(substr($c, 3, 2))];
break 2;
}
}
} elseif ($type === 'png') {
$chars = $getChars(25);
$size = unpack('N*', substr($chars, 16, 8));
}
// COMPLETE
fclose($fp);
if (is_array($size))
$size = array_values($size);
return ($what === 'size') ? $size : [$type, $size];
}