Upload Multiple Files Simultaneously in PHP

This article explains how to upload multiple files at the same time using PHP and the $_FILES superglobal. You will learn how to properly configure your HTML form, understand the structure of the multi-file $_FILES array, and write a secure PHP script to process and save the uploaded files to your server.

1. Create the HTML Form

To upload multiple files, your HTML form must meet two specific requirements: * The enctype attribute must be set to multipart/form-data. * The file input name attribute must end with square brackets ([]), and it must include the multiple attribute.

<form action="upload.php" method="POST" enctype="multipart/form-data">
    <label for="files">Select files:</label>
    <input type="file" id="files" name="attachments[]" multiple>
    <button type="submit" name="submit">Upload Files</button>
</form>

2. Understand the $_FILES Array Structure

When you upload multiple files, PHP organizes the $_FILES superglobal differently than it does for a single file. Instead of grouping the data by file, PHP groups it by file properties.

If you upload three files, $_FILES['attachments'] will be structured like this:

$_FILES['attachments'] = [
    'name' => ['file1.png', 'file2.jpg', 'file3.pdf'],
    'full_path' => ['file1.png', 'file2.jpg', 'file3.pdf'],
    'type' => ['image/png', 'image/jpeg', 'application/pdf'],
    'tmp_name' => ['/tmp/php1', '/tmp/php2', '/tmp/php3'],
    'error' => [0, 0, 0],
    'size' => [12345, 67890, 102456]
];

3. Process the Uploads in PHP

To handle this structure, you need to loop through the array indices. The code below demonstrates how to validate and move each uploaded file to a target directory.

<?php
if (isset($_POST['submit'])) {
    // Define the target directory for uploads
    $uploadDir = 'uploads/';
    
    // Create the directory if it does not exist
    if (!is_dir($uploadDir)) {
        mkdir($uploadDir, 0755, true);
    }

    // Check if files were actually uploaded
    if (!empty($_FILES['attachments']['name'][0])) {
        $files = $_FILES['attachments'];
        $totalFiles = count($files['name']);

        // Loop through each file
        for ($i = 0; $i < $totalFiles; $i++) {
            $fileName = basename($files['name'][$i]);
            $fileTmpName = $files['tmp_name'][$i];
            $fileError = $files['error'][$i];
            $fileSize = $files['size'][$i];
            
            // Check for upload errors
            if ($fileError === UPLOAD_ERR_OK) {
                // Secure the file name and define the destination path
                $targetFilePath = $uploadDir . time() . '_' . $fileName;

                // Move the file from the temporary directory to the target directory
                if (move_uploaded_file($fileTmpName, $targetFilePath)) {
                    echo "File successfully uploaded: " . htmlspecialchars($fileName) . "<br>";
                } else {
                    echo "Error uploading: " . htmlspecialchars($fileName) . "<br>";
                }
            } else {
                echo "Error code $fileError occurred for file: " . htmlspecialchars($fileName) . "<br>";
            }
        }
    } else {
        echo "No files selected.";
    }
}
?>

Key Security Practices

When implementing multiple file uploads, keep these security rules in mind: * Validate file extensions: Use a whitelist (e.g., ['jpg', 'png', 'pdf']) to restrict what file types users can upload. * Limit file size: Check the $files['size'][$i] value to reject files that are too large. * Sanitize file names: Use basename() and prepend a unique identifier (like time() or uniqid()) to prevent users from overwriting existing files on the server.