Drag and Drop File Upload with jQuery and PHP
Many web applications provide a good user experience by offering fast and user-friendly file uploads. Learn how to add a drag and drop file upload to a website that allows users to upload files by dropping them into a specific area on the web page.

Modern web applications hardly use the traditional file input anymore. They provide a user interface where users can drag and drop files to upload and see upload progress as files are being uploaded. They see a response without needing to reload the page after the upload is complete. In this post, we are going to add a drag and drop file upload in jQuery and PHP with a progress bar to show upload progress.
What is Drag & Drop File Upload?
It is a feature that offers faster uploads with a real-time progress bar and without any page reload. Users can simply drag one or multiple files and drop them into a drop a file here box in this feature. The dropped files are automatically sent to the server via an AJAX request. The client-side script initiates a file upload and sends the files to the server-side script for processing.
How to Add a Drag & Drop File Upload to a Website?
Adding this feature to websites involves a few steps, such as creating an HTML page and using HTML5 Drag and Drop API, initiating file upload via AJAX using jQuery and processing the files in a server-side script using PHP. The following are the steps to add this feature:
Step 1: Create an HTML Page with "Drop Files Here" Area
The first step is to create an HTML page with a drop to upload box. Special CSS styles will be applied to the box to make it obvious to the user where to drop the dragged files. We will also allow users to browse and upload files with a button. There will also be a container for progress bar to show the upload progress.
index.html
<!DOCTYPE html>
<html>
<head>
<title>Drag and Drop File Upload with jQuery & PHP - Demo</title>
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/>
<meta content="width=device-width, initial-scale=1, maximum-scale=1" name="viewport" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" />
<link rel="stylesheet" href="css/style.css" />
<script src="js/jquery-3.1.1.min.js" type="text/javascript"></script>
<script src="js/javascript.js" type="text/javascript"></script>
</head>
<body>
<section class="section py-4">
<div class="container">
<div class="mb-4">
<div class="drop-wrapper">
<div id="drop-area" class="drop-area">
<h2>Drop Files Here</h2>
<div class="mb-4">Or</div>
<button type="button" id="btn-browse" class="btn btn-green btn-browse">Browse Files</button>
</div>
<input type="file" id="files-field" name="files" multiple="multiple" hidden="hidden"/>
</div>
<div class="progress-container">
<div id="progress-bar"></div>
</div>
</div>
</div>
</section>
</body>
</html>
Step 2: Handling Drag Events and Uploading Files in JavaScript using jQuery
We will handle the drag and drop events in JavaScript using jQuery. We prepare an array of files and send them to server with an AJAX request. Steps to initiate file upload using AJAX are as follows:
- Define constants for the drop area, browse button and files input field; each constant holds the relevant element object.
- Add a change event listener to the file input field. The listener will call an
uploadFiles()function. - Add click events to the browse files button and the drop area that trigger a click on the file input field.
- Prevent the default drag behaviors for events
dragenter,drageoveranddragleaveand toggle thehighlightclass on the drop area, which will change the CSS styles of the drop area. - Add an event listener for the
ondropevent to remove thehighlightclass from the drop area. Pass the array of files touploadFiles()function to initiate the file upload. - The function
uploadFiles()will first check if thefilesarray is empty. If it is empty stop the code execution and return from here. - Then, we initialize a new
formDataobject, loop through every file and add it to theformDataobject. - We set the
widthof the progress bar to0and clear its text content, in case it contained content for the previous upload. - We initialize a jQuery AJAX request with different parameters. We set the
contentTypetofalseto allow the browser to handle it formultipart/form-data, andprocessDatatofalseto tell the browser not to convert the data into a query string. Then we provide theformDataobject to thedataproperty of the AJAX request. - Inside the
xhrproperty method, we track the file upload progress, update the progress bar accordingly and when the upload has finished, we show an alert with a success message.
javascript.js
$(document).ready(function () {
const dropArea = $("#drop-area");
const browseBtn = $("#btn-browse");
const filesField = $("#files-field");
// Trigger files upload when file input field changes
filesField.on("change", function() {
uploadFiles(this.files);
});
browseBtn.on("click", function() {
$("#files-field").trigger("click");
});
// Trigger click event on files input field when drop area is clicked
dropArea.on("click", function () {
$("#files-field").trigger("click");
});
// Prevent default drag behaviors
dropArea.on("dragenter dragover", function (e) {
e.preventDefault();
e.stopPropagation();
dropArea.addClass("highlight");
});
// Prevent default drag behaviors
dropArea.on("dragleave", function (e) {
e.preventDefault();
e.stopPropagation();
dropArea.removeClass("highlight");
});
dropArea.on("drop", function (e) {
e.preventDefault();
e.stopPropagation();
dropArea.removeClass("highlight");
let files = e.originalEvent.dataTransfer.files;
uploadFiles(files);
});
});
function uploadFiles(files) {
// If files is empty, return from here
if (!files.length) {
return;
}
let formData = new FormData();
// Append each file to form data
$.each(files, function (index, file) {
formData.append("files[]", file);
});
$("#progress-bar")
.css("width", 0)
.empty();
// Initiate an AJAX request to upload files
$.ajax({
url: "process-upload.php",
type: "POST",
data: formData,
contentType: false,
processData: false,
xhr: function () {
let xhr = new window.XMLHttpRequest();
// Track the file upload progress and update progress bar
xhr.upload.addEventListener("progress", function (e) {
let percent = (e.loaded / e.total) * 100;
$("#progress-bar")
.css("width", percent + "%")
.text(`${percent}%`);
}, false);
// Show an alert that upload has finished
xhr.addEventListener("loadend", function () {
setTimeout(function () {
alert("File upload complete.");
}, 200);
}, false);
return xhr;
}
});
}Step 3: Process Uploaded Files on Server-Side (PHP)
The next step after uploading files via AJAX to the server-side script is to handle the file processing in our server-side PHP script. The code in this snippet can be extended for further checks such as maximum file size, file types and any other changes as per the application's requirements. Steps to process uploaded files in PHP in the following code snippet are as follows:
- Check if the superglobal
$_FILESis not empty. - Create an array
$allowed_typesof allowed file types. - Loop through each uploaded file, check if the current file in the loop was uploaded without error, then proceed to the next line of code. Otherwise, skip the file with an error and move on to the next one.
- Store the file type of the current file in a variable
$typein the loop and check if the file type exists in the$allowed_typesarray. - Finally, move the file to the
uploadsdirectory, set the response header to200and return a JSON response with a success message. - As a fallback, set the response code to
400and send a JSON response with a proper error message.
process-upload.php
<?php
// Code to process file uploads
if (!empty($_FILES)) {
$allowed_types = ['image', 'audio', 'video'];
for ($i = 0; $i < count($_FILES['files']['name']); $i++) {
// If there is an error in uploaded file, then skip this file
if ($_FILES['files']['error'][$i] !== UPLOAD_ERR_OK) {
continue;
}
$type = substr($_FILES['files']['type'][$i], 0, 5);
// Check if the file type of uploaded file is allowed
if (in_array($type, $allowed_types)) {
move_uploaded_file($_FILES['files']['tmp_name'][$i], 'uploads/' . $_FILES['files']['name'][$i]);
}
}
// Set response header to 200 - OK, and send data with a success message.
http_response_code(200);
die(json_encode(['success' => 1, 'message' => 'Files successfully uploaded.'], JSON_PRETTY_PRINT);
}
// Set response header to 400 - Bad Request and send data with an error message in response.
http_response_code(400);
die(json_encode(['success' => 0, 'message' => 'Something went wrong! please try again.'], JSON_PRETTY_PRINT);
Step 4: Add Drag & Drop CSS Styles
Finally, we add CSS styles for the entire HTML page, the drop area and the progress bar.
styles.css
* {
box-sizing: border-box;
}
html, body {
margin: 0;
padding: 0;
}
body {
background-color: #f6f6f6;
font-family: "Segoe UI", "Roboto", "Helvetica", sans-serif;
font-size: 15px;
font-weight: normal;
font-style: normal;
line-height: 1.5;
}
.container {
width: 100%;
max-width: 1140px;
margin-right: auto;
margin-left: auto;
padding-right: 15px;
padding-left: 15px;
}
.py-4 {
padding-top: 1rem;
padding-bottom: 1rem;
}
.mb-4 {
margin-bottom: 1rem;
}
.drop-wrapper {
background-color: #ffffff;
border: 1px solid #3b3b3b;
border-radius: 10px;
padding: 10px;
margin-bottom: 1rem;
}
.drop-area {
background-color: #ffffff;
border: 2px dashed #3b3b3b;
border-radius: 10px;
padding: 40px 20px;
text-align: center;
cursor: pointer;
transition: .3s ease;
}
.drop-area.highlight {
border-color: #e65442;
opacity: 0.8;
}
.progress-container {
background-color: #d1d2d3;
width: 100%;
}
#progress-bar {
background-color: #319764;
color: #ffffff;
text-align: center;
width: 0;
transition: width .2s;
}
.btn {
display: inline-block;
padding: 5px 10px;
cursor: pointer;
font: inherit;
}
.btn-green {
background-color: #319764;
border: 1px solid #248A57;
color: #ffffff;
}We just learnt how to add an HTML drag and drop file upload feature to a website using jQuery and PHP. The code snippets provide a basic example of how to add a drag & drop upload area in any PHP application. The code can be modified according to any special requirements of the application.