Image preview and upload using PHP and MySQL database


User experience can be greatly improved on an image upload feature if we enable the user to preview the image they have selected before actually uploading it to the server by clicking the upload button.

In this tutorial, we will create a form that takes two inputs: the user's profile picture (image), and their bio (text). When the user fills the form and clicks on the upload button, we will use our PHP script to grab the form values (the image and the bio) and save the image in our project folder called images. Once the image is saved in the project folder, we will store a record in the database containing the image name and the user's bio.

After saving this info, we will create another page that queries the user profiles from the database displays them on the page with each user's bio against their profile picture.

So let's get started with the implementation.

Create a project folder and call it image-preview-upload. Inside this folder, create a file called form.php and a folder called images for storing the images.

form.php:

<?php include_once('processForm.php') ?>
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Image Preview and Upload PHP</title>
  <!-- Bootstrap CSS -->
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0/css/bootstrap.min.css" />
  <link rel="stylesheet" href="main.css">
</head>
<body>
  <div class="container">
    <div class="row">
      <div class="col-4 offset-md-4 form-div">
        <a href="profiles.php">View all profiles</a>
        <form action="form.php" method="post" enctype="multipart/form-data">
          <h2 class="text-center mb-3 mt-3">Update profile</h2>
          <?php if (!empty($msg)): ?>
            <div class="alert <?php echo $msg_class ?>" role="alert">
              <?php echo $msg; ?>
            </div>
          <?php endif; ?>
          <div class="form-group text-center" style="position: relative;" >
            <span class="img-div">
              <div class="text-center img-placeholder"  onClick="triggerClick()">
                <h4>Update image</h4>
              </div>
              <img src="images/avatar.jpg" onClick="triggerClick()" id="profileDisplay">
            </span>
            <input type="file" name="profileImage" onChange="displayImage(this)" id="profileImage" class="form-control" style="display: none;">
            <label>Profile Image</label>
          </div>
          <div class="form-group">
            <label>Bio</label>
            <textarea name="bio" class="form-control"></textarea>
          </div>
          <div class="form-group">
            <button type="submit" name="save_profile" class="btn btn-primary btn-block">Save User</button>
          </div>
        </form>
      </div>
    </div>
  </div>
</body>
</html>
<script src="scripts.js"></script>

Before I say anything about the form, let's first of all create a styling file named main.css for the form in the root folder of our project.

main.css:

.form-div { margin-top: 100px; border: 1px solid #e0e0e0; }
#profileDisplay { display: block; height: 210px; width: 60%; margin: 0px auto; border-radius: 50%; }
.img-placeholder {
  width: 60%;
  color: white;
  height: 100%;
  background: black;
  opacity: .7;
  height: 210px;
  border-radius: 50%;
  z-index: 2;
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  display: none;
}
.img-placeholder h4 {
  margin-top: 40%;
  color: white;
}
.img-div:hover .img-placeholder {
  display: block;
  cursor: pointer;
}

On the first line of our form.php file, we are including a file that contains our PHP script responsible for receiving the form values and processing them (that is, saving the image in the images folder and creating a corresponding record in the users table in the database).

If you take a look at the form, you will see that we are setting the value of the CSS property display to none; We are doing this because we don't want to display the default HTML input element for file upload. Instead, we will create a different element and style it the way we want and then when the user clicks on our element, we will use JavaScript under the hood to trigger the HTML file input element which is hidden to us.

Now let's add the scripts responsible for triggering the file input element and then also displaying the image for preview.

Create a file called scripts.js in the root of your application and add this code to it:

script.js:

function triggerClick(e) {
  document.querySelector('#profileImage').click();
}
function displayImage(e) {
  if (e.files[0]) {
    var reader = new FileReader();
    reader.onload = function(e){
      document.querySelector('#profileDisplay').setAttribute('src', e.target.result);
    }
    reader.readAsDataURL(e.files[0]);
  }
}

Now when the user clicks on the round image area, the function triggerClick() will trigger a click event on the hidden file input element. When the user selects an image, an onChange event is triggered on the file input field and we can use JavaScript's FileReader() class to temporarily display the image for preview.

When the user clicks the 'Save User' button, the input form will be submitted to the same page. So on that same form.php page, we are including a processForm.php file which contains the code to process our form.

So in the root folder of the project create a file named processForm.php;

processForm.php:

<?php
  $msg = "";
  $msg_class = "";
  $conn = mysqli_connect("localhost", "root", "", "img-upload");
  if (isset($_POST['save_profile'])) {
    // for the database
    $bio = stripslashes($_POST['bio']);
    $profileImageName = time() . '-' . $_FILES["profileImage"]["name"];
    // For image upload
    $target_dir = "images/";
    $target_file = $target_dir . basename($profileImageName);
    // VALIDATION
    // validate image size. Size is calculated in Bytes
    if($_FILES['profileImage']['size'] > 200000) {
      $msg = "Image size should not be greated than 200Kb";
      $msg_class = "alert-danger";
    }
    // check if file exists
    if(file_exists($target_file)) {
      $msg = "File already exists";
      $msg_class = "alert-danger";
    }
    // Upload image only if no errors
    if (empty($error)) {
      if(move_uploaded_file($_FILES["profileImage"]["tmp_name"], $target_file)) {
        $sql = "INSERT INTO users SET profile_image='$profileImageName', bio='$bio'";
        if(mysqli_query($conn, $sql)){
          $msg = "Image uploaded and saved in the Database";
          $msg_class = "alert-success";
        } else {
          $msg = "There was an error in the database";
          $msg_class = "alert-danger";
        }
      } else {
        $error = "There was an erro uploading the file";
        $msg = "alert-danger";
      }
    }
  }
?>

This code receives the input values that was submitted from the form. This input consists of the user image and the bio. On the server, we can access the image file and all related image information such as the image name, size, extension, etc, in the $_FILE[] super global variable while other information such as text is found in the $_POST[] superglobal variable. 

Using the information in the $_FILE[] super global variable, we can validate the image. For instance, our source code can only accept images whose sizes are less than 200kb. Of course, you can always change this value if you want.

You notice in the code above that we are connecting to a database called img-upload. Create this database and create a table called users with the following fields:

users table:

CREATE TABLE `users` (
 `id` int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
 `profile_image` varchar(255) NOT NULL,
 `bio` text NOT NULL
)

Now open the form on your browser and input some info. If everything went well, your image will be uploaded to the images folder in your project and a corresponding record saved in the database.

Displaying Image from Database

Once our image is in the database, displaying it is a breeze. Create a file in the root folder and name it profiles.php.

profiles.php

<?php
  $conn = mysqli_connect("localhost", "root", "", "img-upload");
  $results = mysqli_query($conn, "SELECT * FROM users");
  $users = mysqli_fetch_all($results, MYSQLI_ASSOC);
?>
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Image Preview and Upload</title>
  <!-- Bootstrap CSS -->
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0/css/bootstrap.min.css" />
</head>
<body>
  <div class="container">
    <div class="row">
      <div class="col-4 offset-md-4" style="margin-top: 30px;">
        <a href="form.php" class="btn btn-success">New profile</a>
        <br>
        <br>
        <table class="table table-bordered">
          <thead>
            <th>Image</th>
            <th>Bio</th>
          </thead>
          <tbody>
            <?php foreach ($users as $user): ?>
              <tr>
                <td> <img src="<?php echo 'images/' . $user['profile_image'] ?>" width="90" height="90" alt=""> </td>
                <td> <?php echo $user['bio']; ?> </td>
              </tr>
            <?php endforeach; ?>
          </tbody>
        </table>
      </div>
    </div>
  </div>
</body>
</html>

Simple! This file connects to the database, queries all profile info from the users table and lists the user profiles in a tabular format displaying each user's profile image against their bio. An image is displayed simply by using the image name from the database and pointing to the images folder where the image resides.

Conclusion

I hope you enjoyed this short tutorial. If you have any questions, drop it in the comments below. 

Remember to support by sharing.

Have a nice time.

Awa Melvine

Share Google Plus Linkedin


Comments