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.