How can I only allow certain filetypes on upload in php?

Solution 1:

Put the allowed types in an array and use in_array().

$file_type = $_FILES['foreign_character_upload']['type']; //returns the mimetype

$allowed = array("image/jpeg", "image/gif", "application/pdf");
if(!in_array($file_type, $allowed)) {
  $error_message = 'Only jpg, gif, and pdf files are allowed.';
  $error = 'yes';
}

Solution 2:

edit

I just realized that you want to allow PDF files as well. In that case check out PHP's Fileinfo class and functions. But as far as security goes, you still shouldn't rely on $_FILES[]['type'] :)

I'll leave the rest here in case it helps someone else who finds this question


For checking the mime type of the image, $_FILES[]['type'] could be unsafe. This data is sent by the browser and could be easily spoofed.

You should use the getimagesize() function if you only want to allow images to be uploaded (despite its maybe misleading name). This function won't just give you the size but all the data you will probably need about the image.

I used the following script in an image handling class:

private function load_image_data($image_file) {

    // Firstly, to disambiguate a loading error with a nonexistant file error,
    // check to see if the file actually exists.
    if( ! file_exists($image_file) ) {
        throw new Nonexistent_Image_Exception("The file '{$image_file}' does not exist");
    }

    // We're going to check the return value of getimagesize, so we don't
    // need any pesky warnings or notices popping up, since we're going to
    // stop execution of this function if something goes wrong.
    $image_data = @getimagesize($image_file);

    if( $image_data === false ) {
        throw new Load_Image_Exception("Could not get image data from '{$image_file}'");
    }

    $this->size = new Dimensions($image_data[0], $image_data[1]);
    $this->mime = $image_data['mime'];

}

Notice that getimagesize() returns an associative array containing a 'mime' index. The data here is reliable.

In another function I checked the mime type of the image and converted it to PNG with the appropriate GD function:

private function load_image($image_file) {

    // Suppress warning messages because we're going to throw an
    // exception if it didn't work instead.
    switch( $this->mime ) {
    case 'image/jpeg':
    case 'image/pjpeg':
        $this->image = @imagecreatefromjpeg($image_file);
        break;
    case 'image/gif':
        $this->image = @imagecreatefromgif($image_file);
        break;
    case 'image/png':
        $this->image = @imagecreatefrompng($image_file);
        break;
    default:
        throw new Invalid_Image_Exception("The image was of an invalid type");
    }

    if( $this->image === false ) {
        throw new Load_Image_Exception("Loading of image '{$image_file}' failed");
    }

}

You probably won't need to do all of this, but you can see what mime types appear for the filetypes you have specified. Notice that a jpeg could have two different mime types.

Hope this helps.