Drag and Drop File uploading using JavaScript and PHP

Rahul Ranjan
 17th Jan, 2021
  120 Comments
Drag and Drop File uploading using JavaScript and PHP

File uploading by selecting a file from your desktop and then clicking on the download button to get it uploaded is now old fashion. In this article, we will learn how to upload files directly by using drag and drop events. So, let's get started.

Creating a drag and drop form

Firstly we will create a form with an upload area where you can simply drag and drop files to upload. Here in this form, we will hide our input element and design the form area using CSS.

index.html

<form action="uploader.php" id="myForm" method="post" class="upload_form">
    <input type="file" name="files[]" id="file" class="form_input" multiple=""/>
    <div class="upload_box">
        <h2>Drop files here to upload</h2>
        <p>or</p>
        <label for="file">Select Files</label>
    </div>
</form>

Below is the HTML to display output once the file gets uploaded.

<fieldset>
    <legend>Upload Result</legend>
    <div class="upload_status">Uploading in progress</div>
    <div class="upload_result"></div>
</fieldset>

Adding CSS to the form

Styling form to give drag and drop effect and give better look to form.

style.css

.form_area{
    width: 450px;
    margin: 0px auto;
}
.upload_result{
    height: 100px;
}
.form_input{
    display: none;
}
.upload_form{
    width: 100%;
    height: 250px;
    padding: 25px 0px;
    position: relative;
    font-size: 1.25rem;
    outline-offset: -10px;
    background-color: #c8dadf;
    outline: 2px dashed #323434;
    -webkit-transition: outline-offset .15s ease-in-out, background-color .15s linear;
    transition: outline-offset .15s ease-in-out, background-color .15s linear;
}
.upload_box{
    padding-top: 70px;
    text-align: center;
}
.upload_box h2{
    margin: 0;
    line-height: 1.4;
    font: 400 16px arial;
}
.upload_box p{
    padding: 0px 0 10px;
    font: bold 14px arial;
}
.upload_box label{
    color: #0071a1;
    margin: 12px 0;
    line-height: 3;
    padding: 10px 18px;
    border-radius: 6px;
    background: #f3f5f6;
    font: 400 14px Arial;
    border: 1px solid #0071a1;
}
.upload_status{
    display: none;
    margin: 2px 0;
    color: #ffffff;
    padding: 4px 5px;
    background: #445d54;
    font: 400 14px Arial;
}
.upload_status.success{
    display: block;
    background: green;
}
.upload_status.error{
    display: block;
    background: red;
}
.drag_start{
    outline-offset: -15px;
    outline-color: #c8dadf;
    background-color: #e6f3f7;
}
.image_box{
    float: left;
    width: 80px;
    height: 80px;
    margin: 0px 4px;
    overflow: hidden;
    border: 1px solid #000;
    box-shadow: 1px 1px 0px #000;
}
.image_box.loading{
    background-size: 40px;
    background: url(../icon/loader.gif) 10px no-repeat;
}
.image_box.error{
    background-size: 40px;
    background: url(../icon/warning.png) 10px no-repeat;
}
.image_box img{
    width: 100%;
}

Handling drag-drop event and Ajax functionality 

We are done with HTML and CSS. We will now create a script to handle the drag and drop event & upload functionality. Firstly we will check if drag and drop are supported by the browser or not. Then if supported we will prevent the default behavior of the drag-drop event and we will capture files dropped in the form area. After detecting the drag end event we will upload the file to the server using JavaScript-based ajax script and display the output below our form.

script.js

'use strict';
;( function ( document, window, index )
{
    // verify drag & drop support in browser
    var dragDropSupported = function()
    {
        var div = document.createElement( 'div' );
        return ( ( 'draggable' in div ) || ( 'ondragstart' in div && 'ondrop' in div ) ) && 'FormData' in window && 'FileReader' in window;
    }();
    // IE fix for .remove() function
    if (!('remove' in Element.prototype)) {
        Element.prototype.remove = function() {
            if (this.parentNode) {
                this.parentNode.removeChild(this);
            }
        };
    }
    var form = document.querySelector( '.upload_form' );
    var input = form.querySelector( 'input[type="file"]' ),
    label = form.querySelector( 'label' ),
    droppedFiles = false,
    formSubmit = function()
    {
        var event = document.createEvent( 'HTMLEvents' );
        event.initEvent( 'submit', true, true );
        form.dispatchEvent( event );
    };
    // automatically submit the form on file select
    input.addEventListener( 'change', function( e )
    {
        formSubmit();
    });
    // drag&drop event action
    if( dragDropSupported )
    {
        [ 'drag', 'dragstart', 'dragend', 'dragover', 'dragenter', 'dragleave', 'drop' ].forEach( function( event )
        {
            form.addEventListener( event, function( e )
            {
                e.preventDefault();
                e.stopPropagation();
            });
        });
        [ 'dragover', 'dragenter' ].forEach( function( event )
        {
            form.addEventListener( event, function()
            {
                form.classList.add( 'drag_start' );
            });
        });
        [ 'dragleave', 'dragend', 'drop' ].forEach( function( event )
        {
            form.addEventListener( event, function()
            {
                form.classList.remove( 'drag_start' );
            });
        });
        form.addEventListener( 'drop', function( e )
        {
            droppedFiles = e.dataTransfer.files;
            formSubmit();
        });
    }else{
        alert("Drag & Drop not Supported in this browser.");
    }
    // if the form was submitted
    form.addEventListener( 'submit', function( e )
    {
        e.preventDefault();
        if(form.classList.contains("uploading")) return false;
        form.classList.add("uploading");
        let div=document.createElement("div");
        div.setAttribute("class","image_box loading");
        document.querySelector(".upload_result").appendChild(div);
        let up_status=document.querySelector(".upload_status");
        up_status.setAttribute("class","upload_status");
        document.querySelector(".upload_box>label").innerHTML="Select Files";
        up_status.innerHTML="File upload started...";
        up_status.classList.add("success");
        // gathering the form data
        var ajaxData = new FormData( form );
        if( droppedFiles )
        {
            Array.prototype.forEach.call( droppedFiles, function( file )
            {
                ajaxData.append( input.getAttribute( 'name' ), file );
            });
        }
        //creating JS based ajax request
        var ajax = new XMLHttpRequest();
        ajax.open( form.getAttribute( 'method' ), form.getAttribute( 'action' ), true );
        ajax.onload = function()
        {
            form.classList.remove( 'uploading' );
            up_status.setAttribute("class","upload_status");
            if( ajax.status >= 200 && ajax.status < 400 ){
                let data=JSON.parse( ajax.responseText );
                if(data["status" ]=="success" ){
                    up_status.classList.add("success" );
                    let loader = document.querySelectorAll(".loading, .error" );
                    Array.prototype.forEach.call( loader, function( x ){
                        x.remove();
                    });
                    var files=data["files" ];
                    for(let i=0; i<files.length; i++){
                        let div=document.createElement("div" );
                        div.setAttribute("class" ,"image_box" );
                        let img=document.createElement("img" );
                        img.setAttribute("src" ,files[i]);
                        div.appendChild(img);
                        document.querySelector(".upload_result" ).appendChild(div);
                        up_status.innerHTML="Files uploaded Successfully";
                        up_status.classList.add("success" );
                    }
                }else{
                    up_status.innerHTML = data["message" ];
                    up_status.classList.add("error" );
                    let stat_loading = document.querySelectorAll(".loading" );
                    Array.prototype.forEach.call( stat_loading, function( l ){
                        l.classList.add("error" );
                        l.classList.remove("loading" );
                    });
                }
            }else{
                form.classList.remove( 'uploading' );
                alert( 'Oops! Something went wrong' );
            }
            droppedFiles=false;
        };
        ajax.onerror = function(){
            form.classList.remove( 'uploading' );
            alert( 'Some error occurred. Try again' );
        };
        ajax.send( ajaxData );
    });
}( document, window, 0 ));

PHP script to upload files on the server

Now as we are done with all our form and event control script. We will now create a PHP script to process files sent to the server. 
We will create a script named uploader.php to upload our file on the server and will return the result in JSON format. Also, create a folder named uploads to store uploaded files. 

uploader.php


<?php 
    function is_allowed_type($file_name){
        $file_ext = pathinfo($file_name, PATHINFO_EXTENSION);
        $allowed_types = array("jpg","png","gif","jpeg");
        if(in_array(strtolower($file_ext), $allowed_types)) {
            return true;
        }
        return false;
    };
    
    $uploaded_array=array();
    $path_to_upload="uploads";
    $max_file_size  = 20 * 1024 * 1024; //Max upload size 20MB
    if(isset($_FILES['files']) && !empty(array_filter($_FILES['files']['name']))){
        $i=0;
        foreach ($_FILES['files']['tmp_name'] as $key => $value) {
            if(empty($_FILES['files']['tmp_name'][$key]))
                continue;
            $file_tmpname = $_FILES['files']['tmp_name'][$key]; 
            $file_name = $_FILES['files']['name'][$key]; 
            $file_size = $_FILES['files']['size'][$key];
            $filepath = $path_to_upload."/".$file_name;
            if($file_size > $max_file_size){
                $output = array(
                    'status' => 'error',
                    'message' => "File {$file_name} exceeds uploading limit."
                );
                echo json_encode($output);
                return;
            }
            if(is_allowed_type($file_name)){ 
                if(file_exists($filepath)) { 
                    $filepath = $path_to_upload."/".time().$file_name;                      
                    if( move_uploaded_file($file_tmpname, $filepath)) {
                        $uploaded_array[$i++]=$filepath;
                    }else {
                        $output = array(
                            'status' => 'error',
                            'message' => "Some error occurred while uploadings {$file_name} {$filepath}"
                        );
                        echo json_encode($output);
                        return;  
                    } 
                }else {
                    if( move_uploaded_file($file_tmpname, $filepath)) { 
                        $uploaded_array[$i++]=$filepath; 
                    }else {
                        $output = array(
                            'status' => 'error',
                            'message' => "Some error occurred while uploading {$filepath}"
                        );
                        echo json_encode($output);
                        return;  
                    } 
                }
            }else{
                $output = array(
                    'status' => 'error',
                    'message' => 'Sorry, only images are accepted'
                );
                echo json_encode($output);
                return;
            }
        }
        if(count($uploaded_array)>0){
                $output = array(
                    'status' => 'success',
                    'files' => $uploaded_array
                );
                echo json_encode($output);
                return;
        }
    }else{
        $output = array(
            'status' => 'error',
            'message' => 'No files uploaded.'
        );
        echo json_encode($output);
    }
?>

 Demo      Download


Here in the above article we learned how to create drag and drop file upload functionality. I have used pure Javascript to remove any library dependency. Thanks for reading this article. please provide your important feedback in the comment section below.

Related Tags
Php
Author Of The Post