PHP Upload Multiple Files
Summary: in this tutorial, you’ll learn how to upload multiple files to the server in PHP securely.
Introduction to the PHP upload multiple files
In the previous tutorial, you learned how to upload a single file from a client to the webserver in PHP. All the rules of uploading a single file are relevant to multiple files.
First, the HTML form element must have the enctype
attribute sets to "multipart/form-data"
to enable file uploading. For example:
<form action="index.php" method="post" enctype="multipart/form-data">
Code language: PHP (php)
Second, the file input element must have the multiple
attribute and its name must have the square brackets ([]
) like this:
<input type="file" name="files[]" id="files" multiple />
Code language: PHP (php)
In PHP, you can access the $_FILES['files']
to get the information of the uploaded files:
var_dump($_FILES['files']);
Code language: HTML, XML (xml)
The 'files'
is the name of the file input element.
PHP upload multiple files example
The following example reuses the existing functions and logic developed in the file upload tutorial.
First, create the following project structure:
├── inc
| ├── flash.php
| └── functions.php
├── index.php
├── upload.php
└── uploads
Second, add the following code to the index.php
to create the file upload form:
session_start();
require_once __DIR__ . '/inc/flash.php';
<html lang="en">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>PHP upload multiple files</title>
<link rel="stylesheet" href="https://www.phptutorial.net/app/css/style.css" />
</head>
<body>
'upload') flash(
<main>
<form action="upload.php" method="post" enctype="multipart/form-data">
<div>
<label for="files">Select files to upload:</label>
<input type="file" name="files[]" id="files" multiple required/>
</div>
<div>
<button type="submit">Upload</button>
</div>
</form>
</main>
</body>
</html>
Code language: HTML, XML (xml)
The index.php
does the following:
1) Start a new session or resume an existing session:
session_start();
2) Load the code from the inc/flash.php
file:
require_once __DIR__ . '/inc/flash.php';
Code language: PHP (php)
3) Call the flash()
function to show a message with the name 'upload'
. The flash()
function is defined in the flash.php
file.
'upload') flash(
Code language: HTML, XML (xml)
4) Create an upload form that submits to the upload.php
file.
Third, add the following code to the upload.php
file to validate and upload multiple files:
session_start();
require_once __DIR__ . '/inc/flash.php';
require_once __DIR__ . '/inc/functions.php';
const ALLOWED_FILES = [
'image/png' => 'png',
'image/jpeg' => 'jpg'
];
const MAX_SIZE = 5 * 1024 * 1024; // 5MB
const UPLOAD_DIR = __DIR__ . '/uploads';
$is_post_request = strtolower($_SERVER['REQUEST_METHOD']) === 'post';
$has_files = isset($_FILES['files']);
if (!$is_post_request || !$has_files) {
redirect_with_message('Invalid file upload operation', FLASH_ERROR);
}
$files = $_FILES['files'];
$file_count = count($files['name']);
// validation
$errors = [];
for ($i = 0; $i < $file_count; $i++) {
// get the uploaded file info
$status = $files['error'][$i];
$filename = $files['name'][$i];
$tmp = $files['tmp_name'][$i];
// an error occurs
if ($status !== UPLOAD_ERR_OK) {
$errors[$filename] = MESSAGES[$status];
continue;
}
// validate the file size
$filesize = filesize($tmp);
if ($filesize > MAX_SIZE) {
// construct an error message
$message = sprintf("The file %s is %s which is greater than the allowed size %s",
$filename,
format_filesize($filesize),
format_filesize(MAX_SIZE));
$errors[$filesize] = $message;
continue;
}
// validate the file type
if (!in_array(get_mime_type($tmp), array_keys(ALLOWED_FILES))) {
$errors[$filename] = "The file $filename is allowed to upload";
}
}
if ($errors) {
redirect_with_message(format_messages('The following errors occurred:',$errors), FLASH_ERROR);
}
// move the files
for($i = 0; $i < $file_count; $i++) {
$filename = $files['name'][$i];
$tmp = $files['tmp_name'][$i];
$mime_type = get_mime_type($tmp);
// set the filename as the basename + extension
$uploaded_file = pathinfo($filename, PATHINFO_FILENAME) . '.' . ALLOWED_FILES[$mime_type];
// new filepath
$filepath = UPLOAD_DIR . '/' . $uploaded_file;
// move the file to the upload dir
$success = move_uploaded_file($tmp, $filepath);
if(!$success) {
$errors[$filename] = "The file $filename was failed to move.";
}
}
$errors ?
redirect_with_message(format_messages('The following errors occurred:',$errors), FLASH_ERROR) :
redirect_with_message('All the files were uploaded successfully.', FLASH_SUCCESS);
Code language: HTML, XML (xml)
How the upload.php
works:
1) Start a new session or resume an existing one:
session_start();
2) Load the code from the flash.php
and functions.php
:
require_once __DIR__ . '/inc/flash.php';
require_once __DIR__ . '/inc/functions.php';
Code language: PHP (php)
Note that you should use the flash.php
from the flash message tutorial and functions.php
from the file upload tutorial.
Since the upload.php
deals with multiple files, it will issue multiple error messages, one for each uploaded file.
To make it convenient, we can define a function that returns a single error message from multiple error messages like this:
function format_messages(string $title, array $messages): string
{
$message = "<p>$title</p>";
$message .= '<ul>';
foreach ($messages as $key => $value) {
$message .= "<li>$value</li>";
}
$message .= '<ul>'; return $message;
}
Code language: PHP (php)
And add this format_messages()
function to the functions.php
file.
3) Return an error message if the request method is not POST
or the $_FILES
does not contain the files
field:
$is_post_request = strtolower($_SERVER['REQUEST_METHOD']) === 'post';
$has_files = isset($_FILES['files']);if (!$is_post_request || !$has_files) {
redirect_with_message('Invalid file upload operation', FLASH_ERROR);
}
Code language: PHP (php)
4) Get the uploaded files from $_FILES
and the number of files uploaded:
$files = $_FILES['files'];
$file_count = count($files['name']);
Code language: PHP (php)
5) For each uploaded file, check the error code and validate the file size, type. If an error occurred, add an error message to the $errors
array, skip the current validation loop, and validate the next file.
// validation
$errors = [];
for ($i = 0; $i < $file_count; $i++) {
// get the uploaded file info
$status = $files['error'][$i];
$filename = $files['name'][$i];
$tmp = $files['tmp_name'][$i]; // an error occurs
if ($status !== UPLOAD_ERR_OK) {
$errors[$filename] = MESSAGES[$status];
continue;
}
// validate the file size
$filesize = filesize($tmp);
if ($filesize > MAX_SIZE) {
// construct an error message
$message = sprintf("The file %s is %s which is greater than the allowed size %s",
$filename,
format_filesize($filesize),
format_filesize(MAX_SIZE));
$errors[$filesize] = $message;
continue;
}
// validate the file type
if (!in_array(get_mime_type($tmp), array_keys(ALLOWED_FILES))) {
$errors[$filename] = "The file $filename is allowed to upload";
}
}
Code language: PHP (php)
If an error occurred, redirect back to the index.php
and show the error message:
if ($errors) {
redirect_with_message(format_messages('The following errors occurred:',$errors), FLASH_ERROR);
}
Code language: PHP (php)
Note that we use the format_messages()
function to convert the $errors
array to a single formatted error message.
6) If no error occurs, move each file to the upload directory:
// move the files
for($i = 0; $i < $file_count; $i++) {
$filename = $files['name'][$i];
$tmp = $files['tmp_name'][$i];
$mime_type = get_mime_type($tmp); // set the filename as the basename + extension
$uploaded_file = pathinfo($filename, PATHINFO_FILENAME) . '.' . ALLOWED_FILES[$mime_type];
// new filepath
$filepath = UPLOAD_DIR . '/' . $uploaded_file;
// move the file to the upload dir
$success = move_uploaded_file($tmp, $filepath);
if(!$success) {
$errors[$filename] = "The file $filename was failed to move.";
}
}
Code language: PHP (php)
8) Show the error message if the move has an error. Otherwise, show a success message:
$errors ?
redirect_with_message(format_messages('The following errors occurred:',$errors), FLASH_ERROR) :
redirect_with_message('All the files were uploaded successfully.', FLASH_SUCCESS);
Code language: PHP (php)
Summary
- Set
enctype
attribute of the form to"multipart/form-data"
to enable file uploading in the form. - Set the
multiple
attribute and add square brackets ([]
) to the file input element to upload multiple files. - Always validate the information in the
$_FILES
before processing them. - Use the
move_uploaded_file()
function to move the upload files.