Drag and Drop File Upload with jQuery and AJAX

Utilizing the drag and drop functionality presents a user-friendly method to enable file uploads by effortlessly dropping files into a designated container. Nowadays, numerous websites offer the convenience of uploading files through both drag and drop and traditional file browsing methods, such as PushBullet, Facebook, SlideShare, and many others.

To achieve this functionality, I employ AJAX to seamlessly save the files to the server, which is triggered as soon as a file is dropped onto the specified target container.

Within this tutorial, I show how you can seamlessly implement a similar feature into your own project. By using jQuery AJAX and PHP, you can not only enable the drag and drop file upload but also showcase a thumbnail preview of the successfully uploaded file.

Drag and Drop File Upload with jQuery and AJAX


Table of Content

  1. HTML Structure for Drag and Drop File Upload
  2. CSS Styling
  3. PHP – File Upload and Return File Details for Preview
  4. jQuery – Drag and Drop File Upload
  5. Output
  6. Conclusion

1. HTML Structure for Drag and Drop File Upload

I created a <div class="container"> which contains the file element and a <div class="upload-area" id="uploadfile"> container.

I am using this <div> as file uploading area where the user can drag and drop the file or open File Dialog Box by clicking on it.

<!doctype html>
<html>
    <head>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
        <script src="script.js" type="text/javascript"></script>
    </head>
    <body >

        <div class="container" >
            <input type="file" name="file" id="file">
            
            <!-- Drag and Drop container-->
            <div class="upload-area"  id="uploadfile">
                <h1>Drag and Drop file here<br/>Or<br/>Click to select file</h1>
            </div>
        </div>

    </body>
</html>

2. CSS Styling

.upload-area{
    width: 70%;
    height: 200px;
    border: 2px solid lightgray;
    border-radius: 3px;
    margin: 0 auto;
    margin-top: 100px;
    text-align: center;
    overflow: auto;
}

.upload-area:hover{
    cursor: pointer;
}

.upload-area h1{
    text-align: center;
    font-weight: normal;
    font-family: sans-serif;
    line-height: 50px;
    color: darkslategray;
}

#file{
    display: none;
}

/* Thumbnail */
.thumbnail{
    width: 80px;
    height: 80px;
    padding: 2px;
    border: 2px solid lightgray;
    border-radius: 3px;
    float: left;
}

.size{
    font-size:12px;
}

3. PHP – File Upload and Return File Details for Preview

Setting Up the Upload Folder and “upload.php” File:

Create upload.php file to handle file upload functionality and create an upload folder where all uploaded files will be stored.

Handling File Storage and Thumbnail:

Utilize the upload folder to store the uploaded files. For non-image files, include a default thumbnail named default.png that will be used as the thumbnail representation.

Checking File Type:

When a file is uploaded, verify whether it is an image or not. If it is indeed an image, assign the file location to the variable $src for future use as the thumbnail source.

Preparing the Return Array:

Initialize $return_arr array to hold essential file details such as the file name, size, and location.

Returning Data in JSON Format:

After processing the uploaded file, encode the $return_arr array into JSON format. This enables the seamless communication of file details to the front-end, allowing for smooth integration and real-time file previews.

<?php

/* Getting file name */
$filename = $_FILES['file']['name'];

/* Getting File size */
$filesize = $_FILES['file']['size'];

/* Location */
$location = "upload/".$filename;

$return_arr = array();

/* Upload file */
if(move_uploaded_file($_FILES['file']['tmp_name'],$location)){
     $src = "default.png";

     // checking file is image or not
     if(is_array(getimagesize($location))){
          $src = $location;
     }
     $return_arr = array("name" => $filename,"size" => $filesize, "src"=> $src);
}

echo json_encode($return_arr);

4. jQuery – Drag and Drop File Upload

Preventing Default Page Actions:

This code prevents the default page redirect behavior when files are dragged over the page. It displays the text Drag here inside an h1 element to indicate the drag action.

// preventing page from redirecting
$("html").on("dragover", function(e) {
     e.preventDefault();
     e.stopPropagation();
     $("h1").text("Drag here");
});

$("html").on("drop", function(e) { e.preventDefault(); e.stopPropagation(); });

Handling Drag and Drop Events:

Defines event handlers for the dragenter, dragover, and drop events on the .upload-area element. When a file is dragged over this area, the text Drop is displayed in the h1 element.

Uploading File on Drop:

Upon dropping a file on the .upload-area, retrieves the dropped file and creates a FormData object (fd) to store it. The file is then passed to the uploadData() function to initiate an AJAX request for file upload.

Handling File Selection via Click:

When the user clicks on the upload area (id=”uploadfile”), it triggers a click event on the file input element (id=”file”). The onchange event of the file input allows the user to select a file from their local system, which is then uploaded using the uploadData() function.

Sending AJAX Request for File Upload:

The uploadData() function sends an AJAX request to the server-side script upload.php with the selected or dropped file data in FormData format. The server processes the file upload and returns a JSON response with details about the uploaded file.

Displaying Thumbnails:

Upon a successful AJAX response, the addThumbnail() function is called to display the uploaded file’s thumbnail and its corresponding information, such as the file name and size. If the uploaded file is an image, its thumbnail is shown; otherwise, a default image is displayed.

Bytes Conversion:

Created convertSize() function to convert the file size from bytes to a more human-readable format (KB, MB, etc.), making it easier for users to understand the file’s size.

$(function() {

    // preventing page from redirecting
    $("html").on("dragover", function(e) {
         e.preventDefault();
         e.stopPropagation();
         $("h1").text("Drag here");
    });

    $("html").on("drop", function(e) { e.preventDefault(); e.stopPropagation(); });

    // Drag enter
    $('.upload-area').on('dragenter', function (e) {
         e.stopPropagation();
         e.preventDefault();
         $("h1").text("Drop");
    });

    // Drag over
    $('.upload-area').on('dragover', function (e) {
         e.stopPropagation();
         e.preventDefault();
         $("h1").text("Drop");
    });

    // Drop
    $('.upload-area').on('drop', function (e) {
         e.stopPropagation();
         e.preventDefault();

         $("h1").text("Upload");

         var file = e.originalEvent.dataTransfer.files;
         var fd = new FormData();

         fd.append('file', file[0]);

         uploadData(fd);
    });

    // Open file selector on div click
    $("#uploadfile").click(function(){
         $("#file").click();
    });

    // file selected
    $("#file").change(function(){
         var fd = new FormData();

         var files = $('#file')[0].files[0];

         fd.append('file',files);

         uploadData(fd);
    });
});

// Sending AJAX request and upload file
function uploadData(formdata){

    $.ajax({
         url: 'upload.php',
         type: 'post',
         data: formdata,
         contentType: false,
         processData: false,
         dataType: 'json',
         success: function(response){
              addThumbnail(response);
         }
    });
}

// Added thumbnail
function addThumbnail(data){
    $("#uploadfile h1").remove(); 
    var len = $("#uploadfile div.thumbnail").length;

    var num = Number(len);
    num = num + 1;

    var name = data.name;
    var size = convertSize(data.size);
    var src = data.src;

    // Creating an thumbnail
    $("#uploadfile").append('<div id="thumbnail_'+num+'" class="thumbnail"></div>');
    $("#thumbnail_"+num).append('<img src="'+src+'" width="100%" height="78%">');
    $("#thumbnail_"+num).append('<span class="size">'+size+'<span>');

}

// Bytes conversion
function convertSize(size) {
    var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
    if (size == 0) return '0 Byte';
    var i = parseInt(Math.floor(Math.log(size) / Math.log(1024)));
    return Math.round(size / Math.pow(1024, i), 2) + ' ' + sizes[i];
}

5. Output

View Output


6. Conclusion

I have demonstrated how to implement drag and drop file upload functionality using jQuery, AJAX, and PHP. Customize and add restrictions as needed for your project’s requirements. Enhance user experience by providing an intuitive and secure file uploading system.

For an alternative approach, explore the tutorial on implementing Drag & Drop file upload using the Dropzone library.

If you found this tutorial helpful then don't forget to share.

36 thoughts on “Drag and Drop File Upload with jQuery and AJAX”

    • Add this on top of your .js file (after $(function() {) to support IE compatibility.
      (It prevents Internet Explorer’s default dragging action):

      document.ondragstart = function () { return false; };

      Reply
  1. Quick question Yogesh,

    How would you implement file type restrictions?
    When ever i try and add a function to upload.php any echo error message breaks it.

    Thanks!

    Reply
    • You can check the file extension while file uploading

      $array = explode(‘.’, $_FILES[‘file’][‘name’]);
      $extension = end($array);

      and if the extension is valid then execute the move_uploaded_file() method.

      Reply
  2. Hey thanks for your help !

    But i’ve this error when i use your code :

    Failed to load resource: the server responded with a status of 500 (PLG_SYSTEM_REDIRECT_ERROR_UPDATING_DATABASE)

    Do you have some idea ?

    Reply
  3. Nice tutorial.
    downloaded it and it’s working well in my computer (ngInx server)
    I’m really happy I found it, because I’m working with one web project
    and planning upload there…
    I Tested it with firefox,opera,chrome
    Thanks!

    Reply
  4. Hi,

    Works great but I notice that the thumbnail are rotated if the aspect ration is different that the others. IE; if the original picture is tall, the thumbnail is rotated. If wide, it is not. May freak out the person I am building this for.

    Is there a way to turn this off? I can deal with the css and other stuff.

    Thanks!

    Reply
  5. Hi,
    It’s a Wonderful code, it’s just what I needed.
    Many many many thanks guy 😉
    I modified small things to control the format, max size and limit the number of max uploaded images… works really great 🙂
    If you vant, I would be happy to provide you with changes as required.

    I’m missing a tool I can’t develop !
    How to propose to delete thumbnail with his image and update the remaining images.
    For ex : I’ve posted 4 images, have 4 thumbnails and finally want to delete only the 3rd ?
    Best regards

    Reply
  6. Thank you for sharing this great work of yours.
    I have a rather strange problem,
    The file that I select via the file interface gets uploaded just fine, but the file that I drag and drop does not, it fails the mime_type check in PHP even if it is the same file. I printed the formdata on both the drop and the select file and it shows the same.
    Any ideas? :O

    Reply
  7. Great tutorial – well written and clear.

    I’m actually using Python rather than PHP, so I had to rewrite the server-side code, and I included multiple files support which I don’t think the PHP code does.
    I also need multiples of these on one page, so I modified it to support multiple unique Id’s rather than just one, and to include an additional field to identify which product the images were for. So much easier than starting from scratch!

    Reply

Leave a Reply to retro Cancel reply