How to upload multiple images with preview in PHP, MySQL and jQuery

If you want to upload one or more images with preview and caption using PHP and MySQL, then this topic can guide you. In this topic, we will develop an application using which user can select one or more images, preview selected images and upload them in the server. Also, user can view all uploaded images and delete an image after upload. Using PHP, MySQL and JavaScript/jQuery, we can develop this application.

PHP image upload file size and image type validationFolders and Files

Below is a screenshot of the folder structure and files I am using:

guide to File Upload with PHP and mysql

I have created a folder named 'photos' under 'xampp/htdocs'.

  1. Folder 'cfg' id for database connection PHP script dbconnect.php.
  2. Folder 'css' is used for our custom stylesheet.
  3. Folder 'js' - we will keep our custom JavaScripts file is in this folder.
  4. Folder 'uploads' - All uploaded photos will be stored in this folder
  5. index.php is the page where user can upload, view and delete photos.
  6. process_image.php is the PHP program that uploads, displays and deletes photos.

Below is the screenshot of the page where photos can be uploaded and be displayed:

Upload image using mysql php

Step 1 - Create a table in MySQL database to store image files

Let us create a table named 'images' in MySQL database. Table structure and create table scripts are given below:

Table: images

This table stores image names (captions) and image filenames of all uploaded images

Upload multiple image using PHP, mysql and jQuery

Table has 4 columns.

  1. id - Unique id of each image, it is the primary key and is auto incremented
  2. image_name - Image name (caption) entered by the user while uploading
  3. image_file - File name of uploaded image
  4. upload_dt - Date on which image was uploaded
Create table script for this table is given below, you can use this code to create the table. Also, you can download the code from the download section later in this topic.

images.sql


CREATE TABLE `images` (
  `id` int(11) NOT NULL,
  `image_name` varchar(100) NOT NULL,
  `image_file` varchar(500) NOT NULL,
  `upload_dt` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp()
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

--
ALTER TABLE `images`
  ADD PRIMARY KEY (`id`);

--
ALTER TABLE `images`
  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=1;

Step 2 - Connect to MySQL database (dbconnect.php)

Use below PHP script to connect to MySQL database.

dbconnect.php


<?php
  $server="localhost";
  $userid="root";
  $pwd="";
  $dbname="demo";
  $conn = mysqli_connect($server, $userid, $pwd, $dbname);
  //Check connection
  if (!$conn) 
  	die("Connection Error: " . mysqli_connect_error());
?>

I am using mysqli_connect() function with four parameters.

  1. server - localhost
  2. userid - we are using root user
  3. password - no password for root
  4. database name - our database name is demo

You can also read the topic How to connect to MySQL database in PHP using MySQLi and PDO.

Step 3 - Develop a page to upload and view images (index.php)

This page will give an option to select one or more images (max 5), you can enter caption for each image, preview them and upload them. Once images are uploaded, those will be displayed as thumbnails and you can click on the image to view it in a modal. Also, images can be deleted from the list.

Upload multiple Images into Database and Display it using php

Name of each uploaded image will be unique, uploaded image file name will be the caption entered for the image. Image validation is done in process_images.php.

Form to upload images

We will use a 5 input file fields to select 5 image files and 5 input text fields to enter captions for each image. There will be a space for previewing the image next to each input image field.


<h2>Upload Images - Admin</h2>
<p>Only jpg, jpeg, png, bmp, gif files are allowed. Image size less than 4M.<br><span>Caption is required if image is selected, otherwise image will be ignored</span></p>
<form action="index.php" method="post" id="frmImage" enctype="multipart/form-data" onSubmit = "return validateForm()">
    <?php for ($i = 1; $i <= 5; $i++) { ?>
        <div class="row">
            <div class="form-group col-md-4">
                <p class="file">
                    <input type="file" name="images[]" id="image<?=$i?>" class="images" onchange="imagePreview(this,'imgPrvw<?=$i?>','image<?=$i?>')">
                    <label for="image<?=$i?>">Select Image <?=$i?></label>
                </p>
            </div>
            <div class="form-group col-md-2" id="imgPrvw<?=$i?>">
                <!-- For Image preview -->
                    
            </div>
            <div class="form-group col-md-6">
                <input type="text" class="form-control image_name" name="image_name[]" maxlength = "100" placeholder="Enter a Caption for image <?=$i?>"/>
            </div>
        </div>
    <?php } ?>
    <div class="form-group col-md-12 btn-class">
        <input type="submit" class="btn btn-primary" value="Upload" name="submit">
    </div>
</form>

We have used a PHP loop to write the input fields. So, if you want to increase number of images from 5 to 10, you just need to change the counter from 5 to 10 in the for-loop. A JavaScript function previewImage() is called on onChange event of the input file. Note the ids of file input fields and image previews. As we are writing in a loop, so ids will be as image1, image2, image3... for image files. Similarly, for previewing, they will be imgPrvw1, imgPrvw2, imgPrvw3 etc.

Display uploaded images

After upload is done, images will be displayed just below the form. Here, I am displaying uploaded images after selecting from the images table.


<?php include "cfg/dbconnect.php";
$image_dir = "uploads/";
include "process_images.php"; ?>
<h2>Uploaded Images</h2>
<?php $sql = "select * from images";
$rs = mysqli_query($conn,$sql);
if (mysqli_num_rows($rs) > 0) {?>
    <div class="uploaded-images">
        <?php foreach ($rs as $value) { ?>
            <div class="show-image">
                <a href="javascript:void(0)" data-toggle="modal" data-target="#showImg" class="view" data-id="<?php echo $value['image_file'].",".$value['image_name']; ?>" >
                    <img alt="<?php echo $value['image_name'];?>" src="<?php echo $image_dir.$value['image_file']; ?>" title="View Image"/>
                </a>
                <button class="btn btn-danger" id="<?php echo $value['image_file']; ?>" onclick="deleteImage('<?php echo $value["image_file"]; ?>','<?php echo $value["image_name"];?>')" title="Remove This Photo">×
                </button>
                <div><?php echo $value['image_name'];?></div>
            </div>
        <?php } ?>
    </div>
<?php } 
else {
    echo "<h4>No Images Available</h4>";
} ?>

Upload folder in the server is set as "uploads/". All image names are selected from database table. Then in a loop, we are fetching all images and displaying them.

Modal to display the image, is defined as below in index.php, we are using Bootstrap modal here:


<!-- Modal to display photo -->
<div id="showImg" class="modal fade" role="dialog">
    <div class="modal-dialog">
      <div class="modal-content">
        <div class="modal-header">
          <button type="button" class="close" data-dismiss="modal">×</button>
        </div>
        <div class="modal-body">
        </div>
        <div class="modal-footer">
          <button type="button" class="btn btn-info" data-dismiss="modal">Close</button>
        </div>
      </div>
    </div>
</div>

process_images.php will be executed when the form is submitted with valid data.

Step 4 - Write JavaScript/jQuery to preview images and validate form input(image_scripts.js)

Let us now see the JavaScript functions in image_scripts.js file.

Preview Image - Function ImagePreview()


function imagePreview(input,imgPrvwId,imgId) {
    $('#'+imgPrvwId).html("");
    if (input.files && input.files[0]) {
        var reader = new FileReader();
        reader.onload = function (e) {
            $('#'+imgPrvwId).append('<div><img src="'+e.target.result+'" class="imgprvw">x<button class="btn btn-danger remove" onclick="removeItem(\''+imgPrvwId+'\',\''+imgId+'\')">x</button>x</div>');
        };
        reader.readAsDataURL(input.files[0]);
    }
}

Note the parameters to this function. First parameter is the file object itself; second parameter is the id of the div where image preview will be displayed and third one is the id of the input image file.

For each image, this preview function will be called with different parameters as the ids are dynamic.

Delete a Preview - Function removeItem()

This function is called when user clicks on 'x' button on the image preview. This function takes two parameters, id of the image preview and id of the image file input. See below code:

Below is the code for removeItem() function written in image_scripts.js


function removeItem(imgPrvwId,imgId){
    $("#"+imgPrvwId).html("");
    $("#"+imgId).val("");
}

Function to validate form data

We will check if an image and corresponding caption are given for at least one image before allowing form submission. validateForm() JavaScript function is called when form is submitted. If any image is selected without caption and form is submitted, then that image will be ignored. Let's see the code for this function:


function validateForm(){
    // If no photos selected, do not allow submit
    // If at least one photo is selected with caption then allow form submission 
    var valid = false;
    var image_names = document.getElementsByClassName("image_name");
    var image_files = document.getElementsByClassName("images");
    for(var i=0; i<image_names.length; i++) {
        var image_file = image_files[i].files[0];
        var image_name = image_names[i].value;
        if (image_name != "" && image_file != null) {
            valid = true;
            break;
        }
    }
    if (valid == false){
        alert("Please select at least one image with caption");
        return false;
    }
}

It gets the values of all image files and captions in two arrays. Then in a loop it checks if values are not empty for both image and caption. If at least one row is found for which both image file and caption are having non-empty values, it exits loop with $valid flag as true.

Step 5 - Write PHP code to upload photo (process_images.php)

When the Upload button is clicked, form validation is done first. If validation is successful, process_images.php will execute to upload the images in the server and update database table. Let's see the code:

process_images.php


<?php
// report all errors except E_NOTICE
error_reporting(E_ALL & ~E_NOTICE);
include "cfg/dbconnect.php";
$target_dir = "uploads/";
$msg = ""; 
if (isset($_POST['submit'])) { // if submitted
  $image_name_arr = $_POST['image_name']; // array of image names
  for ($i = 0; $i < 5; $i++) {
    $image_name = trim($image_name_arr[$i]);
    $image_file = $_FILES["images"]["name"][$i];
    $image_tmp = $_FILES["images"]["tmp_name"][$i];

    if (!empty($image_name) && !empty($image_file)){  
      if ($_FILES["images"]["error"][$i] > 0)
        $msg .= "Could not upload:" .$image_file. $_FILES["images"]["error"][$i] . "
"; else { // check file name extension $image_extn = strtolower(pathinfo($image_file,PATHINFO_EXTENSION)); if($image_extn != "jpg" && $image_extn != "png" && $image_extn != "jpeg" && $image_extn != "gif" && $image_extn != "bmp") $msg .= "Could not upload: ".$image_file."-".$image_name." - Invalid file type
"; // check image type else if(exif_imagetype($image_tmp) != IMAGETYPE_GIF && exif_imagetype($image_tmp) != IMAGETYPE_JPEG && exif_imagetype($image_tmp) != IMAGETYPE_PNG && exif_imagetype($image_tmp) != IMAGETYPE_BMP) $msg .= "Could not upload: ".$image_file." - ".$image_name." - not an Image file
"; // Check file size, max 4M. else if ($_FILES["images"]["size"][$i] > 4000000) $msg .= "Could not upload: ".$image_file."-".$image_name."- Image size exceeds 4M
"; else { // check if image with same name already exists $check_sql = "select * from images where image_name = '$image_name'"; $rs = mysqli_query($conn,$check_sql); if (mysqli_num_rows($rs) > 0) $msg .= "Could not upload ".$image_file."-".$image_name."- already exists
"; else{ // all validations are correct, upload image and insert into DB // name image file with the caption given and extension of image file $new_file = $image_name.".".$image_extn; $target_file = $target_dir.$new_file; if(!move_uploaded_file($image_tmp, $target_file)) $msg .= "Could not upload- ".$image_file."-".$image_name."
"; else{ $date = date('Y-m-d'); $sql = "insert into images (image_name,image_file,upload_dt) values ('$image_name','$new_file','$date')"; $result = mysqli_query($conn,$sql); if (!$result) { // insert fails, so delete uploaded image file unlink($target_file); $msg .= "Error in uploading File- ".$image_file."-".$image_name."
"; } } } } } } } // for loop ends } ?>

It processes each image file in a loop, validates image type and size, then uploads the file. If upload is successful then it inserts the image name, file name and date of upload in a database table called 'images'. If database insert fails it removes the uploaded photo using unlink() function.

Step 6 - Scripts to view/delete an uploaded image (image_scripts.js)

View a image in modal

User can click on a image to view it and also user can delete a particular image by clicking on 'x' button displayed on the top right corner of the image. To view the image in the modal, a modal is already defined in index.php. Using jQuery image is displayed in the modal. See the below code from image_scripts.js


// To display image in modal
$(document).on("click", ".view", function () {
    var str = $(this).data('id');
    var arr = str.split(",");  // separate image file name and Name of image
    var image = arr[0];
    var imageName = arr[1];
    var str = '<img src="uploads/'+image+'"><p>'+imageName+'</p>';
    $(".modal-body").html(str);   
});

Delete an uploaded image - Function deleteImage()

This function is called when user clicks on delete (x) button from top right corner of an image. This function is called with two parameters, one is image file name and other is the image name. Function executes Ajax scripts to run process_images.php which deletes the image from database as well as from the server folder. After deletion, it reloads the image list. Below is the code for this function.


function deleteImage(image_file,image_name) {
    if (confirm("Are you sure you want to delete "+image_name+" Image?")) {
        $.ajax({
            type: "POST",
            url: "process_images.php",
            data: {image_file:image_file,delete:true},
            async: false,
            success: function(response) {
                $('.uploaded-images').html(response); 
            }
        });
    }
}

Here, an Ajax request is placed to run process_images.php. Note that data parameter of Ajax scripts, it sends image file name and a flag to delete.

Let's see the code for delete section of process_images.php.


<?php
if (isset($_POST['delete'])){
    $image_file = $_POST['image_file'];
    $sql = "delete from images where image_file = '$image_file'";
    $result = mysqli_query($conn,$sql);
    if (file_exists($target_dir . $image_file))
      unlink($target_dir . $image_file);
    // reload images
    $sql = "select * from images";
    $rs = mysqli_query($conn,$sql); 
    if (mysqli_num_rows($rs) > 0){
      foreach ($rs as $value) { ?>
       <div class="show-image">
          <a href="javascript:void(0)" data-toggle="modal" data-target="#showImg" class="view" data-id="<?php echo $value['image_file'].",".$value['image_name']; ?>" >
          <img alt="<?php echo $value['image_file'];?>" src="<?php echo $target_dir.$value['image_file']; ?>" title="View Image"/></a>

          <button class="btn btn-danger" id="<?php echo $value['image_file']; ?>" onclick="deleteImage('<?php echo $value["image_file"]; ?>','<?php echo $value["image_name"];?>')" title="Remove This Photo">×</button>
          <div><?php echo $value['image_name'];?></div>
       </div>
      <?php } 
    }
    else 
      echo "<h4>No Images Available</h4>";
  }
?>

If delete flag is set, it deletes the image from database table. unlink() php function is used to delete the uploaded file from 'uploads' folder. Once file is removed from the server, all images are refreshed.

Step 7 - Add CSS (style.css)

These are simple styles, you can always use better styles. I have already added style.css in index.php. See below:

style.css


* {
  box-sizing: border-box;
}
h2,h4{
  text-align: center;
  margin-top: 40px;
}
p{
  text-align: center;
}
p span{
  color:red;
}
.file {
  position: relative;
  margin: 0;
}
.file label {
  background: #696969;
  padding: 7px 15px;
  color: #fff;
  font-weight: bold;
  font-size: .9em;
  transition: all .4s;
  cursor: pointer;
}

.file input {
  position: absolute;
  display: inline-block;
  left: 0;
  top: 0;
  opacity: 0.01;
  cursor: pointer;
}
.file input:hover + label,
.file input:focus + label {
  background: #34495E;
  color: #39D2B4;
}
#frmImage{
  margin:auto;
  width:50%;
}
.imgprvw{
  height:50px;
  width:70px;
}
.btn-class{
text-align: center;
margin-top: 20px;
}
.show-image {
  display:inline-block;
  margin:4px -2px;
  text-align:center;
}
.show-image img{
  width:100px;
  height:80px;
}
.show-image .btn {
  margin-top: -47px;
  margin-left: -13px;
  position: relative;
  transform: translate(-50%, -50%);
  -ms-transform: translate(-50%, -50%);
  color: white;
  font-size: 10px;
  padding: 1px 5px;
  border: none;
  cursor: pointer;
  border-radius: 0;
  text-align: center;
}
.modal{
  top:1%;
  left:-13%;
}
.modal-content {
    border: 0;
    width:180%;
}
.modal-body{
    width: 100%;
    height: auto;
    overflow-y:auto;
    padding:10px;
}
.modal-body img{
  width:100%;
  height:auto;
  border:none; 
}
.modal-body p{
  text-align: center;
  font-size: 25px;
  padding-top: 0;
  color: #10109e;
  margin: 0;
  }
.btn-primary{
  background-color: #3b82ac;
  margin-top: 10px;
}
.error{
  color:red;
}
.remove{
  position: absolute;
  left: 72px;
  top: -1px;
  border-radius: 0;
  padding: 0 3px;
  font-size: 12px;
}
.uploaded-images{
  text-align: center;
}

Upload multiple images in PHP and MySQLTest the Application

Make sure in your XAMPP control panel Apache and MySQL services are running. Open the browser and run localhost/photos. You will see the home page as displayed below:

multiple image preview in jquery

Select few images and see if you are able to see the preview of the images. Give caption for each image selected. Click Upload button. Images will be uploaded and you should see them on the listed below Upload button with the name of each images. Click on any image, it should open in a modal. Also delete an images and see the list is refreshed.

Hope you could understand all the steps and you could test it successfully.

upload multiple image in phpImportant Note

  1. For uploading images, you must verify below parameters in php.ini file. You must set file_uploads parameter to "On" in your php.ini. Also review the parameter upload_max_filesize and max_file_uploads. If you restrict file size during upload, make sure the size is less than the size mentioned in php.ini file. Below are the values set for these parameters in my php.ini

    
    ; Whether to allow HTTP file uploads.
    ; http://php.net/file-uploads
    file_uploads=On
    
    ; Maximum allowed size for uploaded files.
    ; http://php.net/upload-max-filesize
    upload_max_filesize=40M
    
    ; Maximum number of files that can be uploaded via a single request
    max_file_uploads=20
    
  2. We have given option for 5 input images, since input fields are created using a loop, you can change the loop count anytime to increase or decrease number of input images.

upload and display multiple images in php source codeDownload Source Code

Download the source code by clicking on the Download button below.

Multiple image upload with previewConclusion

You can use it for product images, you can have more than one image for a product and each image can have a caption along with some other details. Even for an image gallery, you can develop similar type of application.

If you find it useful, you can use it in your project or any other web application with similar requirement.