Building Real ApplicationsExtra· 40 min read

File Uploads & Handling

Let users upload files safely — profile pictures, documents — by validating the type and size and storing the file securely.

What you will learn

  • Build an upload form and read $_FILES
  • Validate file type and size before saving
  • Store uploads safely with a unique name

How uploads work

Almost every real app lets users upload something — a profile photo, a resume, an invoice. In PHP, an uploaded file does not arrive in $_POST; it arrives in a special array called $_FILES. Handling uploads safely is a common project and interview task, because a careless upload form is a serious security hole.

The flow always has three stages: the form sends the file, PHP receives it in a temporary location, and your code validates it and moves it to permanent storage.

  1. The HTML form must use enctype="multipart/form-data" and method="post" so files can be sent.
  2. PHP receives the file into a temporary location and describes it in $_FILES.
  3. You validate it — check the type and size are acceptable.
  4. If it passes, you move it from the temp location to a permanent folder with move_uploaded_file().

The upload form

The form needs one special attribute, enctype, without which the file is not actually sent:

A file-upload form
<!-- upload.html -->
<form action="upload.php" method="post" enctype="multipart/form-data">
  <input type="file" name="photo">
  <button type="submit">Upload</button>
</form>

The key is enctype="multipart/form-data" — it tells the browser to package the file (binary data) along with the form. The <input type="file" name="photo"> creates the choose-file button; photo is the name PHP will use to find this file in $_FILES.

Note: No PHP output yet — this is just the form. Forget the enctype and $_FILES will be empty even though the user picked a file. It is the single most common upload mistake.

Receiving and validating the file

Now the PHP that receives it. We never trust the file blindly — we check its real type and size first, then store it under a fresh, safe name.

Validate type and size, then store safely
<?php
  $file = $_FILES["photo"];

  // 1. basic error + size check (max 2 MB)
  if ($file["error"] !== 0) {
    exit("Upload failed.");
  }
  if ($file["size"] > 2 * 1024 * 1024) {
    exit("File too large (max 2 MB).");
  }

  // 2. allow only real image types
  $allowed = ["image/jpeg", "image/png", "image/webp"];
  $type = mime_content_type($file["tmp_name"]);
  if (!in_array($type, $allowed)) {
    exit("Only JPG, PNG or WebP images are allowed.");
  }

  // 3. give it a safe, unique name and move it
  $ext = pathinfo($file["name"], PATHINFO_EXTENSION);
  $safeName = uniqid("img_") . "." . $ext;
  move_uploaded_file($file["tmp_name"], "uploads/" . $safeName);

  echo "Uploaded as " . htmlspecialchars($safeName);
?>

Reading it in three stages. Stage 1 reads $_FILES["photo"] — an array describing the upload — and rejects it if PHP flagged an error or the size exceeds 2 MB (2 * 1024 * 1024 bytes). Stage 2 uses mime_content_type() to detect the file’s real type by looking inside it (not trusting the filename), and rejects anything not in our $allowed image list. Stage 3 builds a brand-new name with uniqid("img_") so uploads never overwrite each other or carry a dangerous original name, then move_uploaded_file() moves it from the temp spot into the uploads/ folder.

Note: Output (for a valid 800 KB PNG): Uploaded as img_66a1f2c3d4e5b.png The file is now safely in uploads/ under a unique name. A too-big file would have printed File too large (max 2 MB). and a .php disguised as an image would have failed the type check — exactly the attacks we are blocking.

Watch out: Never trust the file’s original name or its extension to decide the type — attackers rename virus.php to photo.jpg. Check the real type with mime_content_type(), store uploads outside any folder PHP will execute, and never let an uploaded file be run as a script.

Q. Where does an uploaded file arrive in PHP?

Answer: Uploaded files arrive in the special $_FILES array, which describes the file (name, type, size, temp location). The form must use enctype="multipart/form-data".

✍️ Practice

  1. Build an upload form and print the uploaded file’s name, size and type from $_FILES.
  2. Reject any file larger than 1 MB or not a JPG/PNG.

🏠 Homework

  1. Build a profile-picture uploader that validates type and size, stores the image with a unique name, and shows it back to the user.
Want to learn this with a mentor?

CodingClave runs guided, project-based training (28-day, 45-day & 6-month batches).

Explore Training →