Published on

File Upload with Progress Bar HTML CSS & JavaScript & Php

FIle_uploader

In this article you will learn the file uploading with progress bar using html css and javascript and php as you can see in the preview image.

Prerequisites:

  • installed xampp server on your computer/laptop
  • start apache server from xampp control panel

Step 1: Create file_uploader Folder in C:\xampp\htdocs\

Step 2: Now create files and folder as shown below

C:\xampp\htdocs\
└── file_uploader
    ├── api       
    |  ├── files
    |  └── uploader.php
    ├── assets
    |  ├── js
    |  |  └── main.js
    |  └── css
    |     └── style.css
    └── index.html

Step 3: now open index.html and copy following code then paste it

file_uploader\index.html
<!DOCTYPE html>
<html lang="en">

    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>File Uploader</title>

        <!-- main css -->
        <link rel="stylesheet" href="assets/css/style.css">

        <!-- box icons -->
        <link href='https://unpkg.com/boxicons@2.0.9/css/boxicons.min.css' rel='stylesheet'>

    </head>

    <body>
        <div class="container">
            <h1>File Uploader</h1>
            <div class="form__container">
                <form action="#" class="form" id="form">
                    <input type="file" name="file" hidden id="file-input" />
                    <i class='bx bx-cloud-upload icon'></i>
                    <p class="helper__text">Browse File to Upload</p>
                </form>
                <section class="progress-area" id="progress-area">
                </section>
                <section class="uploaded-area" id="uploaded-area">
                </section>
            </div>
        </div>

        <!-- js -->
        <script src="assets/js/main.js"></script>
    </body>

</html>

Step 4: After complete your HTML code now open file_uploader\assets\css\styles.css file and paste given CSS code.

file_uploader\assets\css\styles.css
/*===== GOOGLE FONTS =====*/
@import url("https://fonts.googleapis.com/css2?family=Roboto:wght@400;500&display=swap");
/*===== VARIABLES CSS =====*/
:root{
  /*===== Colores =====*/
  --title-color: #F2F2F3;
  --body-color: #0F0F10;
  --form-container-color: #181B1B;
  --first-color: #3B3E40;
  --second-color: #141515;

  /*===== Fuente y tipografia =====*/
  --body-font: 'Roboto', sans-serif;
  --bigger-font-size: 3.5rem;
  --normal-font-size: 1rem;
  --small-font-size: .75rem;
}
  
/*===== BASE =====*/
*,::before,::after{
  box-sizing: border-box;
}
body{
  margin: 0;
  padding: 0;
  font-family: var(--body-font);
  font-size: var(--normal-font-size);
  /* background-color: #f3f2ef; */
}
h1{
  margin: 0;
}

.container{
    height: 100vh;
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    background-color: var(--body-color);
    flex-direction: column;
    gap:.5rem;
}

.container h1{
    font-size: var(--bigger-font-size);
    /* line-height:4rem; */
    background: linear-gradient(var(--first-color), var(--second-color));
    background-clip: text;
    color: transparent;
    text-transform: uppercase;
}

.form__container{
    width: 430px;
    background-color: var(--form-container-color);
    opacity: 1;
    border-radius: .5rem;
    padding: 30px;
    color: var(--title-color);
}


.form__container form{
    height: 167px;
    display: flex;
    cursor: pointer;
    margin: 30px 0;
    align-items: center;
    justify-content: center;
    flex-direction: column;
    border-radius: 5px;
    border: 2px dashed var(--first-color);
}

.icon{
    font-size:4rem;
}

.helper__text{
    font-size: var(--normal-font-size);
    margin-top: .8rem;
}

.row{
    background-color: var(--second-color); 
    list-style: none;
    padding: 15px 20px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    border-radius: .5rem;
    margin-bottom: 10px;
}

.file__profgress-icon{
    font-size: calc(var(--bigger-font-size) - 1rem);
}

.details span{
    font-size: var(--small-font-size);
}

.progress-area .row .content{
    width: 100%;
    margin-left: 15px;
}


.progress-area .details{
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 7px;
}

.progress-area .content .progress-bar{
    height: 6px;
    width: 100%;
    margin-bottom: 4px;
    background: #fff;
    border-radius: 30px;
  }
  .content .progress-bar .progress{
    height: 100%;
    width: 0%;
    background: linear-gradient(var(--first-color), var(--second-color));;
    border-radius: inherit;
  }

  .uploaded-area{
    max-height: 200px;
    overflow-y: scroll;
    /* overflow: hidden; */
  }

  .uploaded-area.onprogress{
    max-height: 150px;
  }

  .uploaded-area::-webkit-scrollbar{
    width: 0px;
  }
  .uploaded-area .row .content{
    display: flex;
    align-items: center;
  }
  .uploaded-area .row .details{
    display: flex;
    margin-left: 15px;
    flex-direction: column;
  }
  .uploaded-area .row .details .size{
    color: #404040;
    /* font-size: 11px; */
  }
 

  .file__check-icon{
      font-size: calc(var(--normal-font-size) + .5rem);
  }

Step 5: Open file_uploader\assets\js\main.js then paste all javascript code into your main.js file

file_uploader\assets\js\main.js
const form = document.getElementById('form'),
    fileInput = document.getElementById('file-input'),
    progressArea = document.getElementById('progress-area'),
    uploadedArea = document.getElementById('uploaded-area');
var ifRunning = false;

// form click Event
form.addEventListener("click", () => {
    if (ifRunning) {
        alert('Please wait another file is uploading..')
        return
    }

    fileInput.click();
})


fileInput.onchange = (e) => {
    let file = e.target.files[0]; //getting file [0] this means if user has selected multiple files then get first one only
    if (file) {
        let fileName = file.name; //getting file name
        if (fileName.length >= 12) { //if file name length is greater than 12 then split it and add ...
            let splitName = fileName.split('.');
            fileName = splitName[0].substring(0, 13) + "... ." + splitName[1];
        }
        uploadFile(fileName); //calling uploadFile with passing file name as an argument
    }
}

// file upload function
function uploadFile(name) {
    let xhr = new XMLHttpRequest(); //creating new xhr object (AJAX)
    xhr.open("POST", "api/uploader.php"); //sending post request to php uploader
    xhr.upload.addEventListener("progress", ({ loaded, total }) => { //file uploading progress event

        let fileLoaded = Math.floor((loaded / total) * 100);  //calculate percentage of loaded file size
        let fileTotal = Math.floor(total / 1000); //gettting total file size in KB from bytes
        let fileSize;
        // if file size is less than 1024 then add only KB else convert this KB into MB
        fileSize = fileTotal < 1024 ? fileTotal + " KB" : (loaded / (1024 * 1024)).toFixed(2) + " MB";

        let progressHTML = `<li class="row">
                                <i class='bx bx-file file__profgress-icon'></i>
                                <div class="content">
                                    <div class="details">
                                        <span class="name">${name} • Uploading</span>
                                        <span class="percent">${fileLoaded}%</span>
                                    </div>
                                <div class="progress-bar">
                                    <div class="progress" style="width: ${fileLoaded}%"></div>
                              </div>
                            </div>
                          </li>`;
        // uploadedArea.innerHTML = ""; //uncomment this line if you don't want to show upload history
        uploadedArea.classList.add("onprogress");
        progressArea.innerHTML = progressHTML;
        if (loaded == total) {
            progressArea.innerHTML = "";
            let uploadedHTML = `<li class="row">
                                    <div class="content upload">
                                        <i class='bx bx-file file__profgress-icon'></i>
                                    <div class="details">
                                        <span class="name">${name} • Uploaded</span>
                                        <span class="size">${fileSize}</span>
                                    </div>
                                    </div>
                                    <i class='bx bx-check file__check-icon'></i>
                                </li>`;
            uploadedArea.classList.remove("onprogress");
            // uploadedArea.innerHTML = uploadedHTML; //uncomment this line if you don't want to show upload history
            uploadedArea.insertAdjacentHTML("afterbegin", uploadedHTML); //remove this line if you don't want to show upload history

            ifRunning = false;
        }
    });
    let data = new FormData(form); //FormData is an object to easily send form data
    xhr.send(data); //send form data
    ifRunning = true
}

Step 6: now at this point your frontend is complete. lets code backend logic open file_uploader\api\uploader.php then copy the given code and past it.

file_uploader\api\uploader.php
<?php
  $file_name =  $_FILES['file']['name']; //getting file name
  
  $tmp_name = $_FILES['file']['tmp_name']; //getting temp_name of file
  
  $file_up_name = time().$file_name; //making file name dynamic by adding time before file name
  
  move_uploaded_file($tmp_name, "files/".$file_up_name); //moving file to the specified folder with dynamic name
?>

That’s all, now you’ve successfully created a File Upload JavaScript with Progress Bar. If your code doesn’t work or you’ve faced any error/problem, please download the source code files from the given download button. It’s free and a .zip file will be downloaded then you’ve to extract it. Once you extracted it, move this project folder inside htdocs or www folder of your XAMPP or WAMP installation directory then start the apache server and run this file on your browser.