验证PHP中文件上载的正确方法 - 包括用户更改文件扩展名?

Currently I check all elements of an image in PHP before I allow it to be uploaded. But when it comes to things like file extensions I'm a bit concerned.

I use the following to only allow files of a certain type to be uploaded:

$allowed_ext = array("jpeg", "jpg", "gif", "png");

$tmp_ext = explode(".", $_FILES["file"]["name"]);
$ext = strtolower(end($tmp_ext));

if ((($_FILES["file"]["type"] == "image/jpeg")
    || ($_FILES["file"]["type"] == "image/jpg")
    || ($_FILES["file"]["type"] == "image/gif")
    || ($_FILES["file"]["type"] == "image/png"))
&& in_array($ext, $allowed_ext)) {
    //Continue
} else {
    //Don't allow
}

But does this prevent all forms of users changing file extensions themselves? e.g. If a user changed the file extension of something malicious to .jpeg or .png - would this prevent it?

I can't find any posts clarifying this, so any help is appreciated!

Short answer, no, you can't rely on the MIME type. Both the type and the file extension are provided by the client.

Looks like you can use getimagesize() for verifying an image, credit to this thread: PHP: $_FILES["file"]["type"] is useless

  1. Take the file extension and match it to the file type, if they do not match: fail.
  2. Using the file format specified by the extension/MIME type call the appropriate imagecreatefrom*() function from the GD library. If it is anything other than an image of the type specified by the extension/MIME type the function will return false.