Drag and Drop File Upload with jQuery and PHP
Modern 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 of the web page.

Modern web applications rarely use the traditional file input. Instead, users are provided with an interface where they can drag files directly onto the area and see a progress bar as files are uploaded. After the file upload is complete, they see a response without needing to reload the page. In this post, we are going to add a drag and drop file upload in jQuery and PHP, along with a progress bar to show upload progress.
What is Drag and Drop File Upload?
A drag & drop file upload is a modern feature that comes with several advantages, such as a better user experience, no page reloads, faster file uploads, and real-time upload progress. With this feature, instead of clicking a file button, users can simply drag one or multiple files and drop them onto a drop a file here box. The dropped files are then automatically uploaded to the server via an AJAX request. When the files are dropped in that area, the client-side script initiates a file upload and sends the files to the server-side script for processing.
Add Drag and Drop File Upload to 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. We are going to add a drag & drop file upload using jQuery and PHP. Steps to add this feature are as follows:
Step 1: Create an HTML Page with Drop Files Here Box
The first step is to create an HTML page with a drop to upload box. The drop box will have specific styling to make it obvious to the user where the user is expected to drop the dragged files. We also add a button allowing users to browse files and upload them, as well as a progress bar container to show the progress of the upload.
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: Handle Drag Events and Upload Files in JavaScript using jQuery
Next, we handle the drag and drop events in JavaScript using jQuery and prepare an array of files to send to the server-side script via 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. In this listener function, we remove thehighlightclass from the drop area, prepare an array of files and pass it to theuploadFiles()function to initiate the file upload. - Inside the function
uploadFiles(), we first check if thefilesarray is empty we return from there without further code execution. - 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 along with the required 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 demonstrated how to easily add an HTML drag and drop file upload feature to a website using jQuery and PHP. The code snippets in this post provide a basic example of how to add a drag & drop upload area in Content Management Systems, admin dashboards, media libraries and other web applications. The code in this post can be extended to meet the specific requirements of a web application.