iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

PHP File Upload

Handling uploaded files is one of the most security-sensitive jobs in PHP. Get the basics right and most footguns go away.

The HTML side

HTML
<form method="post" enctype="multipart/form-data">
    <input type="file" name="upload">
    <button>Upload</button>
</form>

Without enctype="multipart/form-data" the file never gets uploaded.

The PHP side

PHP
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $f = $_FILES['upload'] ?? null;

    if (!$f || $f['error'] !== UPLOAD_ERR_OK) {
        die('Upload failed.');
    }

    // Validate size
    if ($f['size'] > 2 * 1024 * 1024) die('Max 2 MB.');

    // Validate MIME — using fileinfo, not the client-supplied $f['type']
    $mime = mime_content_type($f['tmp_name']);
    if (!in_array($mime, ['image/jpeg', 'image/png'], true)) {
        die('JPEG or PNG only.');
    }

    // Pick a safe destination filename
    $ext  = pathinfo($f['name'], PATHINFO_EXTENSION);
    $name = bin2hex(random_bytes(8)) . '.' . strtolower($ext);
    $dest = __DIR__ . '/uploads/' . $name;

    move_uploaded_file($f['tmp_name'], $dest);
    echo "Saved as $name";
}

Why each check matters

CheckThreat
Verify UPLOAD_ERR_OKPHP-reported partial/over-size uploads.
Cap file sizeDisk-fill DoS.
Detect MIME server-sideBrowser-supplied type is forgeable.
Generate new filenamePath traversal, filename injection.
Store outside docroot, or block PHP executionUploading a .php and running it.
Use move_uploaded_file (not rename)Sanity check it came from an upload.

Size limits

PHP enforces these in php.ini — the smallest wins:

  • upload_max_filesize
  • post_max_size
  • memory_limit
Tip: For files larger than a few MB, consider direct-to-S3 uploads with a pre-signed URL. PHP never touches the bytes — your server stays unloaded.

Example

Example
<?php
// HTML side:
// <form method="post" enctype="multipart/form-data">
//   <input type="file" name="upload">
//   <button>Upload</button>
// </form>
if (isset($_FILES['upload'])) {
    move_uploaded_file($_FILES['upload']['tmp_name'], 'uploads/' . basename($_FILES['upload']['name']));
}
Try it Yourself »

Exercise

Move an uploaded file to its final location with…

($_FILES['upload']['tmp_name'], $dest);

Test yourself

Q1. Form encoding must be…
Q2. Trust client-supplied MIME?
Q3. Move uploads with…

Discussion

Loading…