How to check if an uploaded file is an image without mime type?

倖福魔咒の 提交于 2019-12-17 04:30:41

问题


I'd like to check if an uploaded file is an image file (e.g png, jpg, jpeg, gif, bmp) or another file. The problem is that I'm using Uploadify to upload the files, which changes the mime type and gives a 'text/octal' or something as the mime type, no matter which file type you upload.

Is there a way to check if the uploaded file is an image apart from checking the file extension using PHP?


回答1:


You could use getimagesize() which returns zeros for size on non-images.




回答2:


My thought about the subject is simple: all uploaded images are evil.

And not only because they can contain malicious codes, but particularly because of meta-tags. I'm aware about crawlers that browse the web to find some protected images using their hidden meta-tags, and then play with their copyright. Perhaps a bit paranoid, but as user-uploaded images are out of control over copyright issues, I take it seriousely into account.

To get rid of those issues, I systematically convert all uploaded images to png using gd. This have a lot of advantages: image is clean from eventual malicious codes and meta tags, I only have one format for all uploaded images, I can adjust the image size to fit with my standard, and... I immediately know if the image is valid or not! If the image can't be opened for conversion (using imagecreatefromstring which doesn't care about image format), then I consider the image as invalid.

A simple implementation could look like this:

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);
}

To test it:

header('Content-type: image/png');
imageUploaded('http://www.dogsdata.com/wp-content/uploads/2012/03/Companion-Yellow-dog.jpg', 'php://output');

This does not exactly answer your question as this is the same kind of hack than the accepted answer, but I give you my reasons to use it, at least :-)




回答3:


You can verify the image type by checking for magic numbers at the beginning of the file.

For example: Every JPEG file begins with a "FF D8 FF E0" block.

Here is more info on magic numbers




回答4:


If Uploadify really changes the mime type - i would consider it a bug. It doesn't make sense at all, because that blocks developers from working with mime-type based functions in PHP:

  • finfo_open()
  • mime_content_type()
  • exif_imagetype().

This is a little helper function which returns the mime-type based on the first 6 bytes of a file.

/**
 * 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;
}



回答5:


You can check the first few bytes of the file for the magic number to figure out the image format.




回答6:


Try using exif_imagetype to retrieve the actual type of the image. If the file is too small it will throw an error and if it can't find it it will return false




回答7:


Is it not possible to interrogate the file with finfo_file?

$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mimetype = finfo_file($finfo, $filename); //should contain mime-type
finfo_close($finfo);

This answer is untested but based on this forum discussion on the Uploadify forums.

I would also point out that finfo should "try to guess the content type and encoding of a file by looking for certain magic byte sequences at specific positions within the file" so in my mind this should still work even though Uploadify has specified the wrong mime type.



来源:https://stackoverflow.com/questions/6484307/how-to-check-if-an-uploaded-file-is-an-image-without-mime-type

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!