PHP

Implement Secure File Uploads in PHP

Learn to safely handle file uploads in PHP by validating file types, sizes, and names, significantly reducing the risk of malicious file execution and server compromise.

<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['uploadedFile'])) {
    $uploadDir = 'uploads/'; // Directory where files will be stored
    if (!is_dir($uploadDir)) {
        mkdir($uploadDir, 0755, true); // Create directory if it doesn't exist
    }

    $allowedMimeTypes = ['image/jpeg', 'image/png', 'application/pdf'];
    $maxFileSize = 5 * 1024 * 1024; // 5 MB in bytes

    $file = $_FILES['uploadedFile'];

    // Basic error checking
    if ($file['error'] !== UPLOAD_ERR_OK) {
        echo "File upload failed with error code: " . $file['error'];
        exit;
    }

    // Validate file size
    if ($file['size'] > $maxFileSize) {
        echo "Error: File size exceeds the allowed limit of 5MB.";
        exit;
    }

    // Validate file type (MIME type check)
    $finfo = finfo_open(FILEINFO_MIME_TYPE);
    $mimeType = finfo_file($finfo, $file['tmp_name']);
    finfo_close($finfo);

    if (!in_array($mimeType, $allowedMimeTypes)) {
        echo "Error: Invalid file type. Only JPEG, PNG, and PDF are allowed.";
        exit;
    }

    // Further validation: Check file extension based on MIME type (double-check)
    $extension = pathinfo($file['name'], PATHINFO_EXTENSION);
    $allowedExtensions = [
        'image/jpeg' => ['jpg', 'jpeg'],
        'image/png' => ['png'],
        'application/pdf' => ['pdf']
    ];

    if (!isset($allowedExtensions[$mimeType]) || !in_array(strtolower($extension), $allowedExtensions[$mimeType])) {
         echo "Error: Mismatched file extension for the detected MIME type.";
         exit;
    }


    // Generate a unique filename to prevent overwriting and path traversal
    $newFileName = uniqid('upload_', true) . '.' . strtolower($extension);
    $destinationPath = $uploadDir . $newFileName;

    // Move the uploaded file
    if (move_uploaded_file($file['tmp_name'], $destinationPath)) {
        echo "File uploaded successfully: " . htmlspecialchars($newFileName);
    } else {
        echo "Error: Could not move uploaded file.";
    }
} else {
    echo "
            <form action='' method='post' enctype='multipart/form-data'>
                Select file to upload (Max 5MB, JPG, PNG, PDF):
                <input type='file' name='uploadedFile' id='uploadedFile'>
                <input type='submit' value='Upload File' name='submit'>
            </form>
        ";
}
?>
How it works: This PHP snippet demonstrates secure practices for handling file uploads. It validates the uploaded file's size and performs a critical MIME type check using `finfo_open` to prevent malicious files from being disguised as benign ones. It also cross-references the detected MIME type with the file extension for an extra layer of security. Finally, it generates a unique filename to avoid overwriting existing files and potential path traversal vulnerabilities, then safely moves the file to a designated `uploads` directory.

Need help integrating this into your project?

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

Hire DigitalCodeLabs