PHP

Securely Validate File Uploads in PHP

Implement robust server-side validation for file uploads in PHP, checking file type, size, and potential malicious content to ensure the security of your web application.

<?php

// Define upload directory and allowed file types/sizes
$upload_dir = __DIR__ . '/uploads/';
$allowed_mimes = ['image/jpeg', 'image/png', 'application/pdf'];
$max_file_size = 5 * 1024 * 1024; // 5 MB

if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['user_file'])) {
    $file = $_FILES['user_file'];

    // 1. Check for upload errors
    if ($file['error'] !== UPLOAD_ERR_OK) {
        die('File upload error: ' . $file['error']);
    }

    // 2. Validate file size
    if ($file['size'] > $max_file_size) {
        die('File is too large. Max size is 5MB.');
    }

    // 3. Validate file type (using actual MIME type, not just extension)
    $finfo = finfo_open(FILEINFO_MIME_TYPE);
    $mime_type = finfo_file($finfo, $file['tmp_name']);
    finfo_close($finfo);

    if (!in_array($mime_type, $allowed_mimes)) {
        die('Invalid file type. Only JPG, PNG, PDF are allowed. Detected: ' . $mime_type);
    }

    // 4. Generate a unique, secure filename to prevent path traversal/overwrite
    $extension = pathinfo($file['name'], PATHINFO_EXTENSION);
    $new_file_name = uniqid('upload_', true) . '.' . $extension;
    $destination_path = $upload_dir . $new_file_name;

    // 5. Move the uploaded file to its final, secure destination
    if (move_uploaded_file($file['tmp_name'], $destination_path)) {
        echo 'File uploaded successfully: ' . $new_file_name;
        // Optionally, remove execute permissions on the uploaded file if possible (e.g., chmod($destination_path, 0644);)
    } else {
        die('Failed to move uploaded file.');
    }
} else {
    echo '<form method="POST" enctype="multipart/form-data">';
    echo '    <input type="file" name="user_file">';
    echo '    <button type="submit">Upload File</button>';
    echo '</form>';
}

?>
How it works: This PHP snippet provides a comprehensive example of secure file upload validation. It covers several crucial security checks: verifying `UPLOAD_ERR_OK` to detect general upload problems, validating the file `size` to prevent denial-of-service attacks, and critically, checking the actual file's `mime_type` using `finfo_open` rather than relying solely on the file extension (which can be easily faked). It then generates a `uniqid` to create a secure, unpredictable filename to prevent path traversal and file overwrite vulnerabilities, finally moving the file to a designated `uploads/` directory outside of the web root if possible, or at least in a directory with restricted execution permissions.

Need help integrating this into your project?

Our team of expert developers can help you build your custom application from scratch.

Hire DigitalCodeLabs