Check Image File Type & Size In PHP

Quick Summary
- Accept only JPG and PNG uploads under 1 MB by reading the file's real MIME type with finfo and checking its size in bytes.
- The form needs method post with multipart/form-data encoding, and accepted files move to an uploads/images folder that must exist and be writable.
- The browser-sent type and file name can't be trusted, so the code ignores them and saves each image under a random name with a matching extension.
Before you save an uploaded image, check that it’s the right type and not too large. This PHP snippet accepts JPG and PNG files under 1 MB from a file field named photo and moves them into an uploads/images/ folder.
The form needs method="post", enctype="multipart/form-data" and an <input type="file" name="photo">. Put the code in the PHP file that handles the form. The form’s text fields arrive in $_POST, as explained in reading form data with $_GET and $_POST.
$allowedFileTypes = [
'image/jpeg' => 'jpg',
'image/png' => 'png',
];
if( isset($_FILES['photo']) && $_FILES['photo']['error'] === UPLOAD_ERR_OK ){
$finfo = new finfo(FILEINFO_MIME_TYPE);
$fileType = $finfo->file($_FILES['photo']['tmp_name']);
if( isset($allowedFileTypes[$fileType]) && $_FILES['photo']['size']<1*1024*1024 ){
$fileName = bin2hex(random_bytes(16)).'.'.$allowedFileTypes[$fileType];
move_uploaded_file($_FILES['photo']['tmp_name'],"uploads/images/".$fileName);
}
}How it works
$allowedFileTypesmaps each MIME type you accept to the file extension to save it with. Add or remove entries, such as'image/webp' => 'webp'.- The
errorcheck comes first. If the upload failed, for example because the file is larger than PHP’supload_max_filesizesetting, there’s no file to check. finfolooks at the content of the temporary file and returns its real MIME type. The type in$_FILES['photo']['type']is sent by the browser and can be faked, so the code doesn’t use it.finfocomes from PHP’s Fileinfo extension, which is enabled by default; on Windows,php_fileinfo.dllhas to be enabled inphp.ini.- The
sizein bytes, which PHP measures itself, must be under1*1024*1024, which is 1 MB. Change the first number to raise the limit. move_uploaded_file()moves the file from PHP’s temporary location (tmp_name) touploads/images/under a random name fromrandom_bytes(), with the extension that matches the detected type. The folder must exist and be writable by PHP.
Why not keep the original file name
The name comes from the visitor’s computer. A file with the same name as an earlier upload would overwrite it, and a file named something like image.php could end up on your server even when its content passes as an image. A random name with an extension picked from the detected type avoids both. If you need the original name, store it separately, for example in your database.
Related articles
- sanitizing text input from the same form: htmlspecialchars and filter_input for the other fields
- preventing form resubmission on refresh: stops a page refresh from sending the upload again

