File uploads arrive in the $_FILES superglobal. Always verify the MIME type with finfo, check file size, and use a random filename. Move files with move_uploaded_file() and store uploads outside the web root.
File Upload Handling
if ($_SERVER["REQUEST_METHOD"] === "POST") {
$file = $_FILES["avatar"];
// Check for errors
if ($file["error"] !== UPLOAD_ERR_OK) {
throw new RuntimeException("Upload failed");
}
// Validate size (2MB max)
if ($file["size"] > 2 * 1024 * 1024) {
throw new RuntimeException("File too large");
}
// Validate MIME type (not just extension!)
$finfo = new finfo(FILEINFO_MIME_TYPE);
$mime = $finfo->file($file["tmp_name"]);
$allowed = ["image/jpeg", "image/png", "image/webp"];
if (!in_array($mime, $allowed)) {
throw new RuntimeException("Invalid file type");
}
// Generate safe filename
$ext = pathinfo($file["name"], PATHINFO_EXTENSION);
$filename = bin2hex(random_bytes(16)) . "." . strtolower($ext);
$dest = "/uploads/" . $filename;
move_uploaded_file($file["tmp_name"], $dest);
echo "Uploaded: $filename";
}