PHP

Secure File Uploads with Validation and Storage

Learn to securely handle file uploads in PHP by validating file types, sizes, and storing them safely outside the web root to prevent common vulnerabilities.

<?php
// Define allowed file types and maximum size
$allowed_types = ['image/jpeg', 'image/png', 'application/pdf'];
$max_size = 5 * 1024 * 1024; // 5 MB

// Directory to store uploaded files (MUST be outside web root for security)
$upload_dir = '/var/www/uploads/'; // Example path, adjust as needed

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

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

    // 2. Validate file type (MIME type check)
    // IMPORTANT: Use finfo_file for robust MIME type checking, as $_FILES['type'] can be spoofed.
    $finfo = new finfo(FILEINFO_MIME_TYPE);
    $mime_type = $finfo->file($file['tmp_name']);
    if (!in_array($mime_type, $allowed_types)) {
        die('Invalid file type: ' . htmlspecialchars($mime_type));
    }

    // 3. Validate file size
    if ($file['size'] > $max_size) {
        die('File size exceeds limit.');
    }

    // 4. Generate a unique, cryptographically secure filename
    $extension = pathinfo($file['name'], PATHINFO_EXTENSION);
    $safe_filename = bin2hex(random_bytes(16)) . '.' . $extension;
    $destination_path = $upload_dir . $safe_filename;

    // 5. Move the uploaded file to its final, secure destination
    if (move_uploaded_file($file['tmp_name'], $destination_path)) {
        echo 'File uploaded successfully to: ' . htmlspecialchars($destination_path);
        // Store $safe_filename in database, link to user, etc.
    } else {
        die('Failed to move uploaded file.');
    }
} else {
    // Display a simple upload form
?>
<!DOCTYPE html>
<html>
<head><title>File Upload</title></head>
<body>
    <form action="" method="post" enctype="multipart/form-data">
        <input type="file" name="upload_file" required>
        <button type="submit">Upload</button>
    </form>
</body>
</html>
<?php
}
How it works: This PHP snippet demonstrates secure file uploading practices. It validates file types using `finfo_file` (more robust than `$_FILES['type']`), checks against a maximum size, generates a unique cryptographic filename to prevent path traversal or overwriting, and stores the file in a directory outside the web root. This minimizes risks like arbitrary code execution, XSS, and directory traversal.

Need help integrating this into your project?

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

Hire DigitalCodeLabs