我想检查一个上传的文件是否是一个图像文件(如PNG,JPG,JPEG,GIF,BMP)或其他文件。问题是我正在使用Uploadify上传文件,这些文件会更改MIME类型,并给出“文本/八进制”或其他类型的MIME类型,无论您上传的是哪种文件类型。如何检查上传的文件是否为没有MIME类型的图像?
有没有办法检查上传的文件是否是除了使用PHP检查文件扩展名之外的图像?
我想检查一个上传的文件是否是一个图像文件(如PNG,JPG,JPEG,GIF,BMP)或其他文件。问题是我正在使用Uploadify上传文件,这些文件会更改MIME类型,并给出“文本/八进制”或其他类型的MIME类型,无论您上传的是哪种文件类型。如何检查上传的文件是否为没有MIME类型的图像?
有没有办法检查上传的文件是否是除了使用PHP检查文件扩展名之外的图像?
您可以使用getimagesize()
,它在非图像上返回零大小。
您可以检查magic number文件的前几个字节来确定图像格式。
尝试更多的信息。如果文件太小就会抛出错误,如果找不到则返回错误
我对这个主题的想法很简单:所有上传的图片都是邪恶的。
而且不仅因为它们可以包含恶意代码,而且特别是因为元标记。我了解使用隐藏元标记浏览网页以找到一些受保护图像的抓取工具,然后播放其版权。也许有点偏执狂,但由于用户上传的图片在版权问题上失控,我谨慎考虑。
为了摆脱这些问题,我使用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');
这并不完全回答你的问题,因为这是同一种黑客比接受的答案的,但我给你我的理由使用它,至少:-)
我完全同意@Alain Tiemblo“我使用gd系统地将所有上传的图片转换为png”。这是安全性的一种方式。 – PauloASilva
事实上,我的一位同事指出,如果你允许动画GIF,这是行不通的。真正。 –
我同意你但是...每个人都知道GIF可以被利用([示例])(http://www.phpclasses.org/blog/post/67-PHP-security-exploit-with-GIF-images.html ))。如果您需要支持GIF,也许您必须投入一些时间和精力来过滤/清除格式。 – PauloASilva
如果Uploadify真的改变了MIME类型 - 我会认为它是一个错误。 这是没有意义的,因为开发商块从PHP与基于 MIME类型功能的工作:
这是一个小辅助函数,它返回基于文件的前6个字节的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_file询问文件?
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mimetype = finfo_file($finfo, $filename); //should contain mime-type
finfo_close($finfo);
这个答案是未经测试,而是基于this forum discussion的Uploadify论坛。
我还要指出,finfo应该是"try to guess the content type and encoding of a file by looking for certain magic byte sequences at specific positions within the file",所以在我看来,即使Uploadify指定了错误的MIME类型,它也应该可以工作。
据我所知,这实际上是完成这件事的可接受的手段。如果它们存在,我会对更好的方法有兴趣。 –
文档说它返回一个包含7个元素的数组,我需要检查它的图像是否需要检查哪个元素? –
零和一个宽度和高度。 –