Handle a file upload in PHP by pairing an HTML form that sends its data as enctype="multipart/form-data" with a script that reads the $_FILES superglobal and moves the uploaded file into place with move_uploaded_file(). The example below also checks the file’s size with $_FILES, verifies its real type with mime_content_type(), and stores it under a name you generate with random_bytes() instead of the one the browser sent.

Requirements:

  • PHP 7.0 or newer, for random_bytes() (tested on PHP 8.5)
  • The Fileinfo extension, used by mime_content_type() — bundled and enabled by default since PHP 5.3
  • A web server — Apache, Nginx, or PHP’s built-in server for testing

How To Upload a File in PHP.

The objective is to let a visitor choose a file, send it to the server, validate it, and save it into an uploads folder under a safe, unique name.

Step 1.

Create the form, name it index.html, and copy/paste the following code into it. The enctype="multipart/form-data" attribute is what tells the browser to send the file itself; without it, only the file name arrives.

<!doctype html>
<html>
<head>
    <meta charset="utf-8">
    <title>Upload a File</title>
</head>
<body>
    <form action="upload.php" method="post" enctype="multipart/form-data">
        <input type="file" name="userfile">
        <input type="submit" value="Upload">
    </form>
</body>
</html>

Step 2.

Create the handler, name it upload.php, and copy/paste the following code into it. Each step is numbered in the comments: check the upload succeeded, cap the size, allow only known-safe types by their real content, build a name you control, then move the file.

<?php

// only handle the request when the form was actually submitted
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['userfile'])) {

    $file = $_FILES['userfile'];

    // 1. did the upload itself succeed?
    if ($file['error'] !== UPLOAD_ERR_OK) {
        exit('Upload failed with error code ' . $file['error'] . '.');
    }

    // 2. keep the size sane (2 MB here)
    $maxBytes = 2 * 1024 * 1024;
    if ($file['size'] > $maxBytes) {
        exit('The file is too large. The maximum size is 2 MB.');
    }

    // 3. allow only known-safe types, checked by CONTENT (not the file name)
    $allowed = [
        'image/jpeg'      => 'jpg',
        'image/png'       => 'png',
        'application/pdf' => 'pdf',
    ];
    $mime = mime_content_type($file['tmp_name']);
    if (!isset($allowed[$mime])) {
        exit('The file type "' . $mime . '" is not allowed.');
    }

    // 4. build our OWN name - never trust the client-supplied file name
    $extension   = $allowed[$mime];
    $safeName    = bin2hex(random_bytes(8)) . '.' . $extension;
    $destination = __DIR__ . '/uploads/' . $safeName;

    // 5. move the temporary file into its final home
    if (move_uploaded_file($file['tmp_name'], $destination)) {
        echo 'Uploaded "' . htmlspecialchars($file['name']) . '" ('
           . number_format($file['size']) . ' bytes) and saved it as '
           . $safeName . '.';
    } else {
        echo 'Sorry, the file could not be saved.';
    }
}

Step 3.

Create the uploads folder next to the two files, then start a server and open the form in a browser at http://localhost:8000.

$ mkdir uploads
$ php -S localhost:8000

Result.

Choose a file and click Upload. PHP validates it and saves it into uploads under a random name, then prints a confirmation:

Uploaded "avatar.png" (90,180 bytes) and saved it as 17c8a2fd10d25a6f.png.

PHP page confirming: Uploaded "avatar.png" (90,180 bytes) and saved it as 17c8a2fd10d25a6f.png

If the file is not one of the allowed types, the script rejects it instead of saving it:

The file type "text/plain" is not allowed.

Notes:

  • Server limits win over your code. upload_max_filesize and post_max_size in php.ini cap the upload no matter what your size check says, and a file larger than post_max_size arrives with an empty $_FILES.
  • Never trust the client. Validate by content with mime_content_type(), not by the file name or the browser-sent $_FILES['userfile']['type'] — both can be faked.
  • Store uploads safely. Keep the uploads folder outside the web root, or block execution inside it, so an uploaded .php file can never be run.

References:


Posted

in

by

Leave a Reply

Your email address will not be published. Required fields are marked *