PHP check if file is an image

143,730

Solution 1

Native way to get the mimetype:

For PHP < 5.3 use mime_content_type()
For PHP >= 5.3 use finfo_open() or mime_content_type()

Alternatives to get the MimeType are exif_imagetype and getimagesize, but these rely on having the appropriate libs installed. In addition, they will likely just return image mimetypes, instead of the whole list given in magic.mime.

While mime_content_type is available from PHP 4.3 and is part of the FileInfo extension (which is enabled by default since PHP 5.3, except for Windows platforms, where it must be enabled manually, for details see here).

If you don't want to bother about what is available on your system, just wrap all four functions into a proxy method that delegates the function call to whatever is available, e.g.

function getMimeType($filename)
{
    $mimetype = false;
    if(function_exists('finfo_open')) {
        // open with FileInfo
    } elseif(function_exists('getimagesize')) {
        // open with GD
    } elseif(function_exists('exif_imagetype')) {
       // open with EXIF
    } elseif(function_exists('mime_content_type')) {
       $mimetype = mime_content_type($filename);
    }
    return $mimetype;
}

Solution 2

The getimagesize() should be the most definite way of working out whether the file is an image:

if(@is_array(getimagesize($mediapath))){
    $image = true;
} else {
    $image = false;
}

because this is a sample getimagesize() output:

Array (
[0] => 800
[1] => 450
[2] => 2
[3] => width="800" height="450"
[bits] => 8
[channels] => 3
[mime] => image/jpeg)

Solution 3

Using file extension and getimagesize function to detect if uploaded file has right format is just the entry level check and it can simply bypass by uploading a file with true extension and some byte of an image header but wrong content.

for being secure and safe you may make thumbnail/resize (even with original image sizes) the uploaded picture and save this version instead the uploaded one. Also its possible to get uploaded file content and search it for special character like <?php to find the file is image or not.

Share:
143,730
sf89
Author by

sf89

Updated on June 29, 2020

Comments

  • sf89
    sf89 almost 4 years

    Is there a way to make sure a received file is an image in PHP?

    Testing for the extension doesn't sound very secure to me as you could upload a script and change its extension to whatever you want.

    I've tried to use getimagesize too, but there might be something more suited for that particular problem.

  • sf89
    sf89 about 11 years
    Unfortunately, this seems to have been deprecated.
  • sf89
    sf89 about 11 years
    Yeah this was my gut feeling but I was looking for something that would be precisely suited to get the type of the file as you could trick this method. I've seen this done with Gifs (see here ha.ckers.org/blog/20070604/…).
  • Dead Man
    Dead Man about 11 years
    I just updated my answer. You can try this
  • sf89
    sf89 about 11 years
    Isn't that a bit heavy? I'll look into it though.
  • sf89
    sf89 about 11 years
    Using exif_imagetype seems like what I was looking for. Thanks!
  • designosis
    designosis about 10 years
    Since getimagesize returns false on failure, this can be pared down to $image = getimagesize($mediapath) ? true : false;
  • The Alpha
    The Alpha about 8 years
    if($array = getimagesize($mediapath)) { // true and use the $array if required }
  • Phoenix
    Phoenix almost 8 years
    finfo_fopen, getimagesize, exif_imagetype, mime_content_type are not fully secure.. i took an html code and save as png image.. after this i upload to server using filereader Api in client side and in server side using functions above write.
  • Farid Movsumov
    Farid Movsumov almost 8 years
    Thanks for solution. I think putting @ before is_array is not neccessary in this case.
  • Kushal Suthar
    Kushal Suthar over 7 years
    It will not work while uploading swf file instead of image. swf file will return array.
  • Elnoor
    Elnoor over 7 years
    getimagesize() is much slower. Better to use exif_imagetype()
  • William Bing Hua
    William Bing Hua almost 7 years
    PHP official docs recommend against this secure.php.net/manual/en/function.getimagesize.php
  • Kamarul Anuar
    Kamarul Anuar almost 7 years
    @Phoenix so there's is any better option to check whether the file is image file or not before upload it to server directory? thanks
  • rsz
    rsz almost 7 years
    @WilliamBingHua yeah, they do, but the warning was not there a few years back
  • MrWhite
    MrWhite over 6 years
    finfo_fopen() should be finfo_open() - there is no f before open. "While mime_content_type is removed from PHP5.3" - I don't think it was ever "removed". It did appear to be (temporarily) deprecated, as many comments suggest, although there is no mention of this in the docs anymore. mime_content_type() is part of the Fileinfo extension, which is enabled by default on PHP 5.3+ (except if you are on Windows, when you have to enable it)
  • jave.web
    jave.web almost 6 years
    function fileIsImage($filepath){ return ( strpos(mime_content_type($filepath), 'image/') === 0 ); }
  • jave.web
    jave.web almost 6 years
    Year 2018 PHP docs: mime_content_type (PHP 4 >= 4.3.0, PHP 5, PHP 7) , not any mark of "deprecated" or such...
  • Admin
    Admin over 4 years
    Caution: Do not use getimagesize() to check that a given file is a valid image.
  • Pavel Kenarov
    Pavel Kenarov over 4 years
    NOT WORK ON SVG! TESTED!
  • 6opko
    6opko about 3 years
    Do not use getimagesize() to check that a given file is a valid image. Use a purpose-built solution such as the Fileinfo extension instead. php.net/manual/en/function.finfo-file.php
  • Faizan Anwer Ali Rupani
    Faizan Anwer Ali Rupani over 2 years
    Year 2021 PHP docs mime_content_type (PHP 4 >= 4.3.0, PHP 5, PHP 7, PHP 8), still no indication of "depreciated" notice.
  • ManInTheArena
    ManInTheArena over 2 years
    Whether using getimagesize or finfo_file, as @Sheen mentions, additional checks are necessary. See also: stackoverflow.com/questions/690108/…, stackoverflow.com/questions/21525125/…