Php 如何检查上传的文件是否是没有mime类型的图像?
我想检查上传的文件是图像文件(例如png、jpg、jpeg、gif、bmp)还是其他文件。问题是我使用Uploadify来上传文件,这会改变mime类型,并给出一个“text/octal”或类似的mime类型,无论上传的是哪种文件类型Php 如何检查上传的文件是否是没有mime类型的图像?,php,image-processing,file-upload,upload,mime-types,Php,Image Processing,File Upload,Upload,Mime Types,我想检查上传的文件是图像文件(例如png、jpg、jpeg、gif、bmp)还是其他文件。问题是我使用Uploadify来上传文件,这会改变mime类型,并给出一个“text/octal”或类似的mime类型,无论上传的是哪种文件类型 除了使用PHP检查文件扩展名外,还有没有其他方法可以检查上传的文件是否为图像?您可以使用PHP检查非图像的大小,返回零。您可以检查文件的前几个字节以确定图像格式 您可以通过检查文件开头的幻数来验证图像类型 例如:每个JPEG文件都以一个“FF D8 FF E0”块
除了使用PHP检查文件扩展名外,还有没有其他方法可以检查上传的文件是否为图像?您可以使用PHP检查非图像的大小,返回零。您可以检查文件的前几个字节以确定图像格式 您可以通过检查文件开头的幻数来验证图像类型 例如:每个JPEG文件都以一个“FF D8 FF E0”块开始
以下是有关尝试使用以检索图像的实际类型的详细信息。如果文件太小,它将抛出一个错误,如果它找不到它,它将返回false我对这个主题的想法很简单:所有上传的图像都是邪恶的 这不仅是因为它们可能包含恶意代码,尤其是因为元标记。我知道有些爬虫会浏览网页,使用隐藏的元标记找到一些受保护的图像,然后利用它们的版权进行游戏。也许有点偏执,但由于用户上传的图片无法控制版权问题,我认真考虑了这一点 为了解决这些问题,我使用gd系统地将所有上传的图像转换为png。这有很多好处:图像是从最终的恶意代码和元标记清除,我只有一种格式的所有上传的图像,我可以调整图像大小,以符合我的标准,和我立即知道图像是否有效如果图像不能打开转换(使用它不关心图像格式),那么我认为图像无效。 一个简单的实现可以如下所示:
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');
这不完全回答你的问题,因为这是一种与接受的答案相同的黑客攻击,但是我给你我使用它的理由,至少:-(<)/p> < p>如果上传真的改变了MIME类型-我会认为它是一个bug。 这毫无意义,因为这会阻碍开发人员使用 PHP中基于mime类型的函数:
- ()
- ()
- ()
/**
* 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应该是这样的,即使Uploadify指定了错误的mime类型,它仍然可以工作。据我所知,这实际上是完成这项工作的公认黑客。如果存在更好的方法,我会很感兴趣。文档说它返回一个包含7个元素的数组,我需要检查哪个元素是否是图像?0,1表示宽度和高度。如果不是图像,它似乎只返回false。我接受这一点,但我仍然想知道是否还有其他选择。
exif_imagetype()
显然要快得多。在我看来,这不安全,攻击者可以在第一个字节中“FF D8 FF E0”,然后添加一些可能被执行的php代码,PHP代码也可以通过使用JPG元数据部分注入到有效的JPG文件中。我完全同意@Alain Tiemblo“我使用gd系统地将所有上传的图像转换为png”。这是关于安全性的方法。事实上,我的一位同事指出,如果你允许动画GIF,这是行不通的。是的,我同意你的看法,但是。。。每个人都知道GIF可以被利用()。如果您需要支持GIF,则可能需要花费一些时间和精力来过滤/清理格式。直接对任意数据使用imagecreatefromstring()
,也很危险,因为DoS样式的攻击仍然可能只使用少量请求来填充服务器内存。您应该首先使用公认答案中提到的getimagesize()
,以确保图像格式可读且尺寸合理,而不是直接从任意数据字符串创建整个图像资源(每像素4个字节,一个RGBa位图)。
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mimetype = finfo_file($finfo, $filename); //should contain mime-type
finfo_close($finfo);