Uploading Multiple Files with Progress Bar via Ajax and PHP
Enabling File Uploads in Web Apps: A Critical Component for Dynamic Functionality. Although PHP allows for file uploads, it frequently requires page refreshes. Using jQuery and Ajax, on the other hand, can create a seamless experience, allowing for user-friendly file/image uploads without reloads.
The following example explains how to implement an AJAX-powered progress bar that shows the percentage of real-time upload progress. The steps involved in this feature are as follows:
- Create an HTML form with a file upload form
- Create CSS for styling
- Create jQuery Ajax to render a progress bar during the upload process.
- Create a PHP file to handle the file upload to the server.
Create an HTML form with a file upload form.
First, create index.php and paste the below HTML
<div class="ath_container tile-container ">
<div id="uploadStatus"></div>
<h2 style="margin-bottom:10px">AJAX File Upload with Progress Bar using JavaScript</h2>
<input type="file" id="fileUpload" multiple /> <!-- Add 'multiple' attribute for multiple file selection -->
<br>
<br>
<button onclick="uploadFiles()">Upload</button> <!-- Change function name -->
<div>
<table id="progressBarsContainer">
<!-- Table rows will be dynamically added here -->
</table>
</div> <!-- Container for progress bars -->
<br>
</div>
Create CSS for styling:
Now create style.css and call it in index.php in the header section
* {
margin: 0px;
padding: 0px;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, Roboto, Segoe UI,
Helvetica Neue, Helvetica, Arial, sans-serif;
margin: 0 auto;
-webkit-font-smoothing: antialiased;
box-sizing: border-box;
color: #2f2f2f;
line-height: 1.5;
}
.ath_container {
width: 740px;
margin: 20px auto;
padding: 0px 20px 0px 20px;
}
.ath_container {
width: 820px;
border: #d7d7d7 1px solid;
border-radius: 5px;
padding: 10px 20px 10px 20px;
box-shadow: 0 0 5px rgba(0, 0, 0, .3);
/* border-radius: 5px; */
}
#uploadStatus {
color: #00e200;
}
.ath_container a {
text-decoration: none;
color: #2f20d1;
}
.ath_container a:hover {
text-decoration: underline;
}
.ath_container img {
height: auto;
max-width: 100%;
vertical-align: middle;
}
.ath_container .label {
color: #565656;
margin-bottom: 2px;
}
.ath_container .message {
padding: 6px 20px;
font-size: 1em;
color: rgb(40, 40, 40);
box-sizing: border-box;
margin: 0px;
border-radius: 3px;
width: 100%;
overflow: auto;
}
.ath_container .error {
padding: 6px 20px;
border-radius: 3px;
background-color: #ffe7e7;
border: 1px solid #e46b66;
color: #dc0d24;
}
.ath_container .success {
background-color: #48e0a4;
border: #40cc94 1px solid;
border-radius: 3px;
color: #105b3d;
}
.ath_container .validation-message {
color: #e20900;
}
.ath_container .font-bold {
font-weight: bold;
}
.ath_container .display-none {
display: none;
}
.ath_container .inline-block {
display: inline-block;
}
.ath_container .float-right {
float: right;
}
.ath_container .float-left {
float: left;
}
.ath_container .text-center {
text-align: center;
}
.ath_container .text-left {
text-align: left;
}
.ath_container .text-right {
text-align: right;
}
.ath_container .full-width {
width: 100%;
}
.ath_container .cursor-pointer {
cursor: pointer;
}
.ath_container .mr-20 {
margin-right: 20px;
}
.ath_container .m-20 {
margin: 20px;
}
.ath_container table {
border-collapse: collapse;
border-spacing: 0;
width: 100%;
border: 1px solid #ddd;
margin-top: 20px;
}
.ath_container table th,
.ath_container table td {
text-align: left;
padding: 5px;
border: 1px solid #ededed;
width: 50%;
}
tr:nth-child(even) {
background-color: #f2f2f2
}
.ath_container .progress {
margin: 20px 0 0 0;
width: 300px;
border: 1px solid #ddd;
padding: 5px;
border-radius: 5px;
}
.ath_container .progress-bar {
width: 0%;
height: 24px;
background-color: #4CAF50;
margin-top: 15px;
border-radius: 12px;
text-align: center;
color: #fff;
}
@media all and (max-width: 780px) {
.ath_container {
width: auto;
}
}
.ath_container input,
.ath_container textarea,
.ath_container select {
box-sizing: border-box;
width: 200px;
height: initial;
padding: 8px 5px;
border: 1px solid #9a9a9a;
border-radius: 4px;
}
.ath_container input[type="checkbox"] {
width: auto;
vertical-align: text-bottom;
}
.ath_container textarea {
width: 300px;
}
.ath_container select {
display: initial;
height: 30px;
padding: 2px 5px;
}
.ath_container button,
.ath_container input[type=submit],
.ath_container input[type=button] {
padding: 8px 30px;
font-size: 1em;
cursor: pointer;
border-radius: 25px;
color: #ffffff;
background-color: #6213d3;
border-color: #9554f1 #9172bd #4907a9;
}
.ath_container input[type=submit]:hover {
background-color: #f7c027;
}
::placeholder {
color: #bdbfc4;
}
.ath_container label {
display: block;
color: #565656;
}
@media all and (max-width: 400px) {
.ath_container {
padding: 0px 20px;
}
.ath_container {
width: auto;
}
.ath_container input,
.ath_container textarea,
.ath_container select {
width: 100%;
}
}
Create jQuery Ajax:
Now create jQuery to render a progress bar during the upload process and create ajax function to upload the file.
function uploadFiles() {
var fileInput = document.getElementById('fileUpload');
var files = fileInput.files;
for (var i = 0; i < files.length; i++) {
var allowedExtensions = ['.jpg', '.jpeg', '.png', '.pdf', '.svg', '.zip', '.docx', '.xlsx'];
var fileExtension = files[i].name.substring(files[i].name.lastIndexOf('.')).toLowerCase();
if (allowedExtensions.includes(fileExtension)) {
uploadFile(files[i]);
} else {
alert('Invalid file type: ' + fileExtension);
}
}
}
function uploadFile(file) {
var formData = new FormData();
formData.append('file', file);
var progressBarContainer = document.createElement('div'); // Container for progress bar and file name
progressBarContainer.className = 'progress-container';
var fileName = document.createElement('div'); // Display file name
fileName.className = 'file-name';
fileName.textContent = file.name;
//progressBarContainer.appendChild(fileName);
var progressBar = document.createElement('div'); // Create a new progress bar element
progressBar.className = 'progress-bar';
progressBar.id = 'progressBar_' + file.name;
progressBarContainer.appendChild(progressBar);
var progressBarsContainer = document.getElementById('progressBarsContainer');
var newRow = document.createElement('tr'); // Create a new table row
var newCell = document.createElement('td'); // Create a new table cell
var newCell2 = document.createElement('td'); // Create a new table cell
newCell.appendChild(fileName);
newCell2.appendChild(progressBarContainer);
newRow.appendChild(newCell);
newRow.appendChild(newCell2);
progressBarsContainer.appendChild(newRow);
var xhr = new XMLHttpRequest();
xhr.upload.addEventListener('progress', function(event) {
if (event.lengthComputable) {
var percent = Math.round((event.loaded / event.total) * 100);
progressBar.style.width = percent + '%';
progressBar.innerHTML = percent + '%';
}
});
xhr.addEventListener('load', function(event) {
var uploadStatus = document.getElementById('uploadStatus');
uploadStatus.innerHTML = event.target.responseText;
// Reset the input field of type "file"
document.getElementById('fileUpload').value = '';
});
xhr.open('POST', 'upload.php', true);
xhr.send(formData);
}
Finally our index.php will be:
<!DOCTYPE html>
<html>
<head>
<title>multiple File Upload with Progress Bar using jQuery AJAX</title>
<style>
</style>
<link rel="stylesheet" type="text/css" href="style.css" />
</head>
<body>
<div class="ath_container tile-container ">
<div id="uploadStatus"></div>
<h2 style="margin-bottom:10px">AJAX File Upload with Progress Bar using JavaScript</h2>
<input type="file" id="fileUpload" multiple placeholder="choose file or browse" /> <!-- Add 'multiple' attribute for multiple file selection -->
<br>
<br>
<button onclick="uploadFiles()">Upload</button> <!-- Change function name -->
<div>
<table id="progressBarsContainer">
<!-- Table rows will be dynamically added here -->
</table>
</div> <!-- Container for progress bars -->
<br>
</div>
<script>
function uploadFiles() {
var fileInput = document.getElementById('fileUpload');
var files = fileInput.files;
for (var i = 0; i < files.length; i++) {
var allowedExtensions = ['.jpg', '.jpeg', '.png', '.pdf', '.svg', '.zip', '.docx', '.xlsx'];
var fileExtension = files[i].name.substring(files[i].name.lastIndexOf('.')).toLowerCase();
if (allowedExtensions.includes(fileExtension)) {
uploadFile(files[i]);
} else {
alert('Invalid file type: ' + fileExtension);
}
}
}
function uploadFile(file) {
var formData = new FormData();
formData.append('file', file);
var progressBarContainer = document.createElement('div'); // Container for progress bar and file name
progressBarContainer.className = 'progress-container';
var fileName = document.createElement('div'); // Display file name
fileName.className = 'file-name';
fileName.textContent = file.name;
//progressBarContainer.appendChild(fileName);
var progressBar = document.createElement('div'); // Create a new progress bar element
progressBar.className = 'progress-bar';
progressBar.id = 'progressBar_' + file.name;
progressBarContainer.appendChild(progressBar);
var progressBarsContainer = document.getElementById('progressBarsContainer');
var newRow = document.createElement('tr'); // Create a new table row
var newCell = document.createElement('td'); // Create a new table cell
var newCell2 = document.createElement('td'); // Create a new table cell
newCell.appendChild(fileName);
newCell2.appendChild(progressBarContainer);
newRow.appendChild(newCell);
newRow.appendChild(newCell2);
progressBarsContainer.appendChild(newRow);
var xhr = new XMLHttpRequest();
xhr.upload.addEventListener('progress', function(event) {
if (event.lengthComputable) {
var percent = Math.round((event.loaded / event.total) * 100);
progressBar.style.width = percent + '%';
progressBar.innerHTML = percent + '%';
}
});
xhr.addEventListener('load', function(event) {
var uploadStatus = document.getElementById('uploadStatus');
uploadStatus.innerHTML = event.target.responseText;
// Reset the input field of type "file"
document.getElementById('fileUpload').value = '';
});
xhr.open('POST', 'upload.php', true);
xhr.send(formData);
}
</script>
</body>
</html>
Create a PHP file to handle the file upload to the server.
<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['file'])) {
$file = $_FILES['file'];
// file will be uploaded to the following folder
// you should give sufficient file permissions
$uploadDir = 'uploads/';
// unique file name generated
$fileName = uniqid() . '_' . $file['name'];
// moving the uploaded file from temp location to our target location
if (move_uploaded_file($file['tmp_name'], $uploadDir . $fileName)) {
echo 'File uploaded successfully.';
} else {
echo 'Failed to upload file.';
}
}