
Good content takes time and effort to come up with.
Please consider supporting us by just disabling your AD BLOCKER and reloading this page again.
Hello Friends! In this article you will learn how to upload multiple files in PHP.
This article covers
NOTE: I have added the complete code in GitHub repository. You can find it here Multiple File Upload
Basic knowledge of PHP, HTML & I hope you already know how to do file upload if not then refer this article
The following is the basic HTML code for multiple file uploads make sure you have enctype="multipart/form-data"
in form tag, product_images[]
is an array in input type=file
tag & multiple
must be added to input element.
In the following example I would like to upload multiple product images, this might not be the realistic example but hope it servers for your understanding.
<form action="store_product.php" method="post" enctype="multipart/form-data">
<div>
<label for="product_images">Select Product</label> <br>
<!--
Basically you get the product list from database.
For the sake of demonstration I am hard coding
-->
<select name="product_id" id="product_id">
<option value="1">Product 1</option>
<option value="2">Product 2</option>
</select>
</div> <br>
<div>
<label for="product_images">Product Images</label> <br>
<input type="file" name="product_images[]" id="product_images" multiple>
</div> <br>
<div>
<input type="submit" value="Upload Product Images">
</div>
</form>
NOTE: I would like to store the images/files in disk ie., specific path and not in my database. By saving the images or any files as BLOB in database will increase the complexity, consumes lot of space & even reduces the efficiency of CRUD operations.
Following is the simple design of the products
& product_images
table inside invoice
database.
/** Creating database with name invoice */
CREATE DATABASE `invoice`;
/** Once we create we want to switch to invoice so that we can add products table */
USE `invoice`;
/** Products table to hold the products data */
CREATE TABLE `products` (
`id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`name` VARCHAR(30),
`product_invoice` VARCHAR(255),
PRIMARY KEY (`id`)
);
/** Product Images */
CREATE TABLE `product_images` (
id INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
product_id INT(11) UNSIGNED NOT NULL,
product_image VARCHAR(100) NOT NULL,
PRIMARY KEY (`id`),
FOREIGN KEY (`product_id`) REFERENCES `products` (`id`)
);
For the sake of demonstration I have the following 2 rows inside products table
INSERT INTO `products` (`id`, `name`, `product_image`)
VALUES
(1, 'Product 1', '98767461589180160d435607145066fc9c3b5069d336f11a9.jpg'),
(2, 'Product 2', '61545675589180160d435607145066fc9c3b5069d336f11a9.jpg');
The following is the code to connect to the database which we created above. I am using PDO
connection, which is very advanced than mysql
or mysqli
functions.
<?php
$host = 'localhost';
$db_name = 'invoice';
$db_username = 'root';
$db_password = 'root';
$dsn = 'mysql:host='. $host .';dbname='. $db_name;
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
];
try {
/** $pdo is the connection object which I will be using for all my datbase operations */
$pdo = new PDO($dsn, $db_username, $db_password);
} catch (PDOException $e) {
exit($e->getMessage());
}
Once you fill the form and submit you will get somewhat similar to the following output.
store_product.php
Lets debug the form uploaded
echo '<pre>';
print_r($_FILES['product_images']);
exit;
Output
Array
(
[name] => Array
(
[0] => tempro1991266572.png
[1] => tempro1913737454.png
)
[type] => Array
(
[0] => image/png
[1] => image/png
)
[tmp_name] => Array
(
[0] => /Applications/MAMP/tmp/php/php70g7x1
[1] => /Applications/MAMP/tmp/php/phppHPzVH
)
[error] => Array
(
[0] => 0
[1] => 0
)
[size] => Array
(
[0] => 874
[1] => 880
)
)
Since looping into them and parsing might be difficult lets format the above. In the below code I am just looping the files and just arranging based on keys ie name, tmp_name etc.
function rearrange_files($files)
{
$file_array = [];
foreach ($files as $file_key => $file) {
foreach ($file as $index => $file_value) {
$file_array[$index][$file_key] = $file_value;
}
}
return $file_array;
}
Using the above function we will get the rearranged files as follows
Array
(
[0] => Array
(
[name] => tempro1991266572.png
[type] => image/png
[tmp_name] => /Applications/MAMP/tmp/php/php3YrETt
[error] => 0
[size] => 874
)
[1] => Array
(
[name] => tempro1913737454.png
[type] => image/png
[tmp_name] => /Applications/MAMP/tmp/php/phpm1vF67
[error] => 0
[size] => 880
)
)
Ah! This looks clean, very understandable and more easy to work on.
Now lets add the bits and pieces to make the basic multiple form upload work
<?php
session_start();
require_once 'db.php';
function rearrange_files($files)
{
/** above I have added function code **/
}
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
/** array variable to hold errors */
$errors = [];
$product_id = $_POST['product_id'];
$product_images = $_FILES['product_images'];
/** Add form validation */
if (empty($product_images)) {
$errors[] = 'Product invoice file required';
}
if (empty($product_id)) {
$errors[] = 'Select product you want to add image';
}
/** Check if the product exists in your database */
$product_stmt = $pdo->prepare("
SELECT
id, name
FROM
`products`
WHERE
id = :product_id
");
$product_stmt->execute([
':product_id' => $product_id,
]);
$product = $product_stmt->fetchObject();
if (!$product) {
$errors[] = 'Selected product does not exist!';
}
/** If there are any form errors then redirect back */
if (count($errors) > 0) {
$_SESSION['errors'] = $errors;
header('Location: index.php');
}
/** $_FILES will have the upload file details in PHP */
$arranged_files = rearrange_files($_FILES['product_images']);
foreach ($arranged_files as $product_image) {
/** I am using pathinfo to fetch the details of the PHP File */
$file_name = $product_image['name'];
$file_size = $product_image['size'];
$file_tmp = $product_image['tmp_name'];
$pathinfo = pathinfo($file_name);
$extension = $pathinfo['extension'];
$file_extensions = ['pdf', 'xls', 'jpeg', 'jpg', 'png', 'svg', 'webp'];
/** Since I want to rename the File I need its extension
* which will be obtained with above $phpinfo variable
* */
/** generate random inage name */
$new_file_name = rand(0, 10000000).time().md5(time()).'.'.$extension;
move_uploaded_file($file_tmp, './uploads/product_images/'. $new_file_name);
$product_image = $pdo->prepare("
INSERT INTO
`product_images` (`product_id`, `product_image`)
VALUES
(:product_id, :product_image)
")
->execute([
':product_id' => $product->id,
':product_image' => $new_file_name,
]);
}
$_SESSION['success'] = 'Products added successfully';
header('location: index.php');
exit;
} else {
header('location: index.php');
exit;
}
In the above code the validation is not added for all the files while doing upload we can perform simple validation as follows
/** File strict validations */
/** File exists */
if (!file_exists($file_tmp)) {
$errors[] = 'File your trying to upload not exists';
}
/** Check if the was uploaded only */
if (!is_uploaded_file($file_tmp)) {
$errors[] = 'File not uploaded properly';
}
/** Check for the file size 1024 * 1024 is 1 MB & 1024 KB */
if ($file_size > (1024 * 1024)) {
$errors[] = 'Uploaded file is greater than 1MB';
}
/** Check File extensions */
if (!in_array($extension, $file_extensions)) {
$errors[] = 'File allowed extensions '. implode(', ', $file_extensions);
}
if (count($errors) > 0) {
$_SESSION['errors'] = $errors;
header('location: index.php');
exit;
}
The simple validation can be performed within foreach loop as shown below
foreach ($arranged_files as $product_image) {
/** The above validation code */
}
Hope you got some idea on upload multiple files in PHP.
Composer Install v/s Composer Update
What Is Composer? How Does It Work? Useful Composer Commands And Usage
Dependency Dropdowns With Javascript And PHP
Supervisor For Laravel Queue Scheduling
NGINX Security Best Practices & Optimization
Factory States For Clean And Fluent Laravel Testing
Use Different PHP Versions In Ubuntu / Linux
Unable to prepare route [{fallbackPlaceholder}] for serialization. Uses Closure In Laravel
Push Files To CPanel / Remote Server using FTP Software FileZilla
What Is Method Chaining In PHP?