PHP Image Upload (Secure Full Code)
In this lesson: Upload images in PHP safely — type and size checks, unique names, move_uploaded_file and preview — full code.
What we are building
An image upload lets users send a picture — a profile photo, a product image — to your server. It has two parts: an HTML form that sends the file, and PHP that receives, checks and saves it. Doing the checks properly is important, because uploads are a common security weak point.
$_FILES array, with a temporary path you then move to a real folder.The upload form
<form method="post" action="upload.php"
enctype="multipart/form-data">
<input type="file" name="photo">
<button type="submit">Upload</button>
</form>
The key part is enctype="multipart/form-data" — without it the file itself is not sent, only its name. The input's name ("photo") is how PHP finds it.
Reading $_FILES
<?php
$file = $_FILES["photo"];
echo $file["name"]; // original name
echo $file["size"]; // size in bytes
echo $file["tmp_name"]; // temporary path on server
?>
PHP puts the upload in $_FILES["photo"]. The important field is tmp_name — the temporary location where PHP saved the file until you move it.
Checking type and size
<?php
$file = $_FILES["photo"];
$allowed = ["jpg", "jpeg", "png"];
$ext = strtolower(pathinfo($file["name"], PATHINFO_EXTENSION));
if ($file["size"] > 2 * 1024 * 1024) {
echo "File too big (max 2MB)";
} elseif (!in_array($ext, $allowed)) {
echo "Only JPG and PNG allowed";
} elseif (!getimagesize($file["tmp_name"])) {
echo "Not a real image";
} else {
echo "OK to save";
}
?>
We check the size, allow only safe extensions, and confirm it is a genuine image with getimagesize(). All three checks matter — a bad file can be disguised.
Saving the file
<?php
$newName = "uploads/" . uniqid() . "." . $ext;
if (move_uploaded_file($file["tmp_name"], $newName)) {
echo "Uploaded as $newName";
}
?>
We generate a unique name with uniqid() (never trust the user's file name) and move the file with move_uploaded_file, which also confirms it was a real upload.
Security tips
- Rename the file to a value you generate — do not keep the user's name.
- Allow only image extensions and verify with
getimagesize(). - Limit the size to avoid huge uploads filling your disk.
- Never allow
.phpor other executable files to be uploaded.
Common mistakes
- Missing
enctype. Then the file is not sent, only its name. - Trusting the browser's file type. Verify with
getimagesize(), not just the reported type. - Keeping the user's file name. Rename it to avoid clashes and hidden scripts.
- Using rename instead of
move_uploaded_file. The latter also checks it was a genuine upload.
Summary
- Uploads need
enctype="multipart/form-data"on the form. - PHP receives the file in
$_FILES, with atmp_namepath. - Check size, allowed extension, and confirm with
getimagesize(). - Save with
move_uploaded_fileunder a generated name. - Never keep the user's name or allow
.phpuploads.
Next, validate the surrounding form with form validation, or store the file path in MySQL.
Frequently Asked Questions
How does file upload work in PHP?
enctype="multipart/form-data". PHP receives it in the $_FILES array, which holds the file's name, type, size and a temporary path. You then move it to a permanent folder.Why must the form have enctype="multipart/form-data"?
multipart/form-data encoding tells the browser to send the actual file content, so PHP can receive it.How do I check the uploaded file is really an image?
getimagesize() (which fails for non-images), and allow only safe extensions like jpg and png. Do not trust the file name or the browser-reported type alone.What does move_uploaded_file do?
move_uploaded_file() moves it from there to your chosen folder. Using this function (not a plain rename) also confirms the file was a real upload, which is safer.