How to Upload Files with PHP

File upload is one of the common needs in many web applications — from profile photos and PDF documents to CSV files for data import. PHP provides a built-in file upload mechanism...

How to Upload Files with PHP

File upload is one of the common needs in many web applications — from profile photos and PDF documents to CSV files for data import. PHP provides a built-in file upload mechanism that's easy to use, but it requires extra care when it comes to security. This article will guide you in building a functional and secure file upload system from scratch.

How File Upload Works in PHP

When a user submits a form with a file, PHP receives that file as the $_FILES array. The file is temporarily stored in the server's temporary folder before we move it to the destination location using move_uploaded_file(). Important: the temporary file is automatically deleted if you don't move it right away.

Creating the Upload Form

An HTML form for file upload must have the enctype="multipart/form-data" attribute and the POST method:

<!-- upload.html -->
<form action="process_upload.php" method="POST" enctype="multipart/form-data">
    <label for="photo">Choose a Photo:</label>
    <input type="file" name="photo" id="photo" accept="image/*" required>
    <br>
    <button type="submit">Upload</button>
</form>

The accept="image/*" attribute in HTML is only a hint to the browser — it can't be relied on as a security validation. The real validation must still be done on the server side.

Processing the Upload in PHP

Create a process_upload.php file that handles receiving and storing the file:

<?php
// process_upload.php

$upload_dir = __DIR__ . '/uploads/';

// Make sure the uploads folder exists
if (!is_dir($upload_dir)) {
    mkdir($upload_dir, 0755, true);
}

// Check whether the file was sent successfully
if (!isset($_FILES['photo']) || $_FILES['photo']['error'] !== UPLOAD_ERR_OK) {
    $error_code = $_FILES['photo']['error'] ?? -1;
    die("Upload failed. Error code: $error_code");
}

$file = $_FILES['photo'];

// 1. Validate the maximum size (2 MB)
$max_size = 2 * 1024 * 1024; // 2 MB in bytes
if ($file['size'] > $max_size) {
    die("File is too large. Maximum 2 MB.");
}

// 2. Validate the allowed MIME type
$allowed_types = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'];
$finfo = new finfo(FILEINFO_MIME_TYPE);
$mime_type = $finfo->file($file['tmp_name']);

if (!in_array($mime_type, $allowed_types)) {
    die("File type not allowed. Only JPEG, PNG, GIF, and WebP.");
}

// 3. Create a unique file name to avoid collisions
$extension = pathinfo($file['name'], PATHINFO_EXTENSION);
$new_filename = uniqid('img_', true) . '.' . strtolower($extension);
$destination = $upload_dir . $new_filename;

// 4. Move the file from temporary to the destination
if (move_uploaded_file($file['tmp_name'], $destination)) {
    echo "Upload successful! File saved as: $new_filename";
} else {
    echo "Failed to move the file. Check the uploads folder permissions.";
}

Understanding the $_FILES Array

When a file is uploaded, PHP fills $_FILES['input_name'] with five keys:

  • name — the original file name from the user's computer.
  • type — the MIME type sent by the browser (don't fully trust it).
  • tmp_name — the temporary file path on the server.
  • error — the error code (0 means success / UPLOAD_ERR_OK).
  • size — the file size in bytes.

Multiple File Upload

To allow uploading many files at once, add the multiple attribute to the input and use a field name with square brackets:

<input type="file" name="documents[]" multiple accept=".pdf,.doc,.docx">
<?php
if (isset($_FILES['documents'])) {
    $files = $_FILES['documents'];
    $count = count($files['name']);

    for ($i = 0; $i < $count; $i++) {
        if ($files['error'][$i] === UPLOAD_ERR_OK) {
            $original_name = basename($files['name'][$i]);
            $destination = __DIR__ . '/uploads/' . uniqid() . '_' . $original_name;
            move_uploaded_file($files['tmp_name'][$i], $destination);
            echo "File '$original_name' uploaded successfully.<br>";
        }
    }
}

Common Upload Error Codes

  • UPLOAD_ERR_OK (0) — success.
  • UPLOAD_ERR_INI_SIZE (1) — the file exceeds upload_max_filesize in php.ini.
  • UPLOAD_ERR_FORM_SIZE (2) — the file exceeds MAX_FILE_SIZE in the HTML form.
  • UPLOAD_ERR_PARTIAL (3) — the file was only partially uploaded.
  • UPLOAD_ERR_NO_FILE (4) — no file was selected.

File Upload Security Tips

  • Always validate the MIME type using finfo, not just the file extension or $_FILES['type'].
  • Use a new server-generated file name (for example with uniqid()) — don't use the original name from the user directly.
  • Store files outside the public folder if possible, or make sure the uploads folder can't execute PHP.
  • Add a .htaccess file in the uploads folder with the content: php_flag engine off to prevent PHP execution.

Conclusion

File upload with PHP is quite easy, but security is something you can't ignore. Always validate on the server side by checking the file size, the MIME type accurately using finfo, and use a safe file name. By following this guide, you already have an upload system that works well and is protected from potential exploits.

upload file php php native upload cara upload gambar php validasi upload php php file upload move_uploaded_file php
Read Also

Here are some related articles that might help expand your knowledge:

Share this article
Back to Blog
🚀 Partner Recommendation

Need Premium Source Code & Business Apps?

Access Laravel applications, POS systems, School Management, Clinic Software, ERP solutions, and ready-to-use premium source code at GudangCode.

GudangCode
  • ✔ Premium Source Code
  • ✔ Ready-to-Use Systems
  • ✔ Lifetime Updates
  • ✔ Lifetime Membership
  • ✔ Daily App Updates
Join Membership →