Create Your Own DROPZONE (Drag and Drop File Uploads)

 
Prerequisites
  • Web Methods in ASP.NET
  • JavaScript
  • jQuery
  • jQuery UI
  • Ajax using jQuery
  • HTML
Here I have implemented drag and drop file uploads using jQuery, Ajax, Web Methods and a Web Handler. For a better understanding I have divided the article into the following 5 parts:
  1. HTML
  2. Use of jQuery-UI
  3. WebHandler
  4. WebMethod
  5. Registering the Events for Drag N Drop in JavaScript
1. HTML 
 
Here I have used div#dropzone as a container in which I will be dropping all the images that I want to upload.

The div#MSG acts like a popup that is used to denote that the file is being uploaded. By default it is hidden and only shows the file being uploaded.
  1. <div id="MSG">  
  2.    <img src="loading.gif" alt="Uploading File" />  
  3. </div>  
  4.    <div id="dropzone">  
  5. </div>  
2. Use of jQuery-UI
 
The jQuery-UI contains the function sortable that helps in sorting the file by dragging them to the position where you want them to be.
The function disableSelection disables any kind of select, actually it is not required in this scenario but it is a good practice to do so. In a scenario where you want to drag and drop some text you may find that the browser gets confused with the selection of text with the dragging of text
 
Note: The sortable() function doesn't make the div#dropzone sortable, but the child elements in it.
  1. $("#dropzone").sortable();  
  2. $("#dropzone").disableSelection();   
3. WebHandler
 
Here I am using a WebHandler to upload files, basically the handlers does the heavy lifting.The WebHandler has a function called ProcessRequest, actually It is not exactly a part of the web handler but is overridden as the handler implements the IHttpHandler Interface. The function ProcessRequest has a parameter of type HttpContext, the object of class HttpContext provides a reference to the intrinsic server objects like Request, Response, Session and Server available with the HTTP Request. In the code below you will find that I have used a GUID to generate a Unique ID and concatenating it with the file name so that in any case the user tries to upload images with the same file name then it should not be overwritten. Once the files are saved the method sends a responseText to the client. I have used it to denote the status of the update by text  "Success", if successful, else I am sending the error message in the responseText since I will use it to confirm the upload on the page.
  1. public void ProcessRequest(HttpContext context)      
  2. {      
  3.     try      
  4.     {      
  5.         if (context.Request.Files.Count > 0)  //Compare File Count    
  6.         {      
  7.             string FileName = "";      
  8.             HttpFileCollection files = context.Request.Files;      
  9.             for (int i = 0; i < files.Count; i++)      
  10.             {      
  11.                 HttpPostedFile file = files[i];      
  12.                 Guid id = Guid.NewGuid();      
  13.                 FileName = id + "__" + file.FileName;      
  14.                 string fName = context.Server.MapPath("Images/" + FileName);      
  15.                 file.SaveAs(fName);      
  16.             }      
  17.             context.Response.ContentType = "text/plain";      
  18.             context.Response.Write("Success");      
  19.         }      
  20.     }      
  21.     catch (Exception ex)      
  22.     {      
  23.         context.Response.ContentType = "text/plain";      
  24.         context.Response.Write(ex.Message);      
  25.     }      
  26.    

4. WebMethod
 
Here I have made 2 Web Methods called GetFileList and DeleteImage. By declaring the function as a WebMethod we are exposing the server-side function such that the method can be called from a remote web client.
  1.     [WebMethod]  
  2.     public static string GetFileList()  
  3.     {  
  4.         //This function is used to collect list of Files Names from the Images folder.  
  5.         //This function returns the data in JSON format  
  6.         //I am using a function called ConvertDataTabletoString to serialize a Datatable into a JSON String  
  7.         CommonFunction com = new CommonFunction();  
  8.         string[] filePaths = Directory.GetFiles(HttpContext.Current.Server.MapPath("Images/"));  
  9.         DataTable dt = new DataTable();  
  10.         dt.Columns.Add("File");  
  11.         foreach (string file in filePaths)  
  12.         {  
  13.             dt.Rows.Add(Path.GetFileName(file));  
  14.         }  
  15.         return com.ConvertDataTabletoString(dt);  
  16.     }  
  17.   
  18.     [WebMethod]  
  19.     public static string DeleteImage(string fileName)  
  20.     {  
  21.         //This function is used to delete a particular Image with the help of the FileName  
  22.         try  
  23.         {  
  24.             File.Delete(HttpContext.Current.Server.MapPath("Images/") + fileName);  
  25.             return "Success";  
  26.         }  
  27.         catch (Exception)  
  28.         {  
  29.             return "Failed";  
  30.         }  
  31.     } 
5. Registering the Events for Drag N Drop in JavaScript
 
Here is the best part of this article, register events to detect drag and drop. To do so the browser provides events like:
  • ondragenter: Detects the dragged element's entry on the droppable target.

  • ondragover: Detects the dragged element is over the droppable target.

  • ondragleave: Detects the dragged element leaves the droppable target.

  • ondrop: Detects the dragged element is dropped on the droppable target.
 NOTE: the events are fired on droppable elements i.e div#dropzone and not on the draggable elements
  1. var dz = document.querySelector('#dropzone');  
  2.     dz.addEventListener('dragenter', handleDragEnter, false);//Register Event dragenter  
  3.     dz.addEventListener('dragover', handleDragOver, false);//Register Event dragover  
  4.     dz.addEventListener('dragleave', handleDragLeave, false);//Register Event dragleave  
  5.     dz.addEventListener('drop', handleDrop, false);//Register Event drop 
Here I will use the function handleDrop() to handle the drop event. This function then uploads the dropped file to the server using jQuery Ajax on the Client-Side and WebHandler on the Server-Side. How I have implemented it, you can find it in the following code.

Complete Code
  1. $(document).ready(function () {    
  2.       var dz = document.querySelector('#dropzone');    
  3.       dz.addEventListener('dragenter', handleDragEnter, false);//Register Event dragenter    
  4.       dz.addEventListener('dragover', handleDragOver, false);//Register Event dragover    
  5.       dz.addEventListener('dragleave', handleDragLeave, false);//Register Event dragleave    
  6.       dz.addEventListener('drop', handleDrop, false);//Register Event drop    
  7.   
  8.       GetFileDetails();// Load all The Images on PageLoad    
  9.   
  10.       $("#dropzone").sortable();    
  11.       $("#dropzone").disableSelection();    
  12.   });    
  13.   
  14.   function handleDragOver(e) {    
  15.       if (e.preventDefault) {    
  16.           e.preventDefault(); // Necessary. Allows us to drop.    
  17.       }    
  18.       this.classList.add('over');    
  19.   
  20.       return false;    
  21.   }    
  22.   
  23.   function handleDragEnter(e) {    
  24.       // If you have used the DropZone you must have noticed that when you drag an item into the browser the gray area(The DropZone)is hilighted by dotted line at its border    
  25.       // well here is how I do it I just add border to the div...    
  26.       // I Have created ta class called over which basically has the styles to hilight the div.     
  27.       // but only when the you are draging any file on the browser    
  28.       this.classList.add('over');    
  29.   
  30.   
  31.   }    
  32.   
  33.   function handleDragLeave(e) {    
  34.       // while draging If you move the cursour out of the DropZone, then the hilighting must be removed    
  35.       // so here I am removing the class over from the div    
  36.       e.preventDefault();    
  37.       this.classList.remove('over');    
  38.   
  39.   }    
  40.   
  41.   //On Drop of file over the DropZone(I have Elaborated the process of What Happen on Drop in Points)    
  42.   function handleDrop(e) {    
  43.       //1st thing to do is Stop its default event, If you won't then the browser will end up rendering the file    
  44.       e.preventDefault();    
  45.       //2nd Checking if the the object e has any files in it.    
  46.       //    actually the object named "dataTransfer" in the object e is the object that hold the data that is being dragged during a drag and drop operation    
  47.       //    dataTransfer object can hold one or more files    
  48.       if (e.dataTransfer.files.length == 0) {    
  49.           this.classList.remove('over');    
  50.           return;// if no files are found then there is no point executing the rest of the code so I return to the function.    
  51.       }    
  52.       var files = e.dataTransfer.files;    
  53.       //3rd  Here I am using an object of FormData() to send the files to the server using AJAX    
  54.       //     The FormData object lets you compile a set of key/value pairs to send using AJAX    
  55.       //     Its primarily intended for use in sending form data    
  56.       var data = new FormData();    
  57.       for (var i = 0, f; f = files[i]; i++) {    
  58.           data.append(files[i].name, files[i]);//Here I am appending the files from the dataTransfer object to FormData() object in Key(Name of File) Value(File) pair    
  59.       }    
  60.       // The operation of Uploading the file consumes time till the time the browser almost freezes     
  61.       this.classList.remove('over');    
  62.   
  63.       //4th  Once I have got all my files in the object of FormData() now I am ready to send the files to server to using AJAX    
  64.       var options = {};    
  65.       options.url = 'FileUploader.ashx';//URL      
  66.       options.type = 'post';//Post Method    
  67.       options.data = data;    
  68.       options.async = false;//synchronous Call       
  69.       options.contentType = false;    
  70.       options.processData = false;    
  71.       options.beforeSend = function () {    
  72.           ShowPopup();//POPUP used to show the uploading is under progress    
  73.       };    
  74.       options.error = function () {    
  75.           alert('Problem uploading file');    
  76.           HidePopup();    
  77.       };    
  78.       options.complete = function (response) {    
  79.           HidePopup();//Once the process is completed POPUP is removed    
  80.           GetFileDetails();//This function is used to bind the div#DropZone with images. I am calling it again to update the page with new Images    
  81.       };    
  82.       $.ajax(options);    
  83.   
  84.   
  85.   }    
  86.   
  87.   var overlay = $('<div id="overlay"></div>');    
  88.   //By default the popup is hidden.    
  89.   //ShowPopup is used to show popup    
  90.   function ShowPopup() {    
  91.       //the body is appended with the the div#overlay which gives the dark background to the popup    
  92.       overlay.appendTo(document.body);    
  93.       $('#MSG').show();    
  94.   }    
  95.   //HidePopup is used to hide the popup    
  96.   function HidePopup() {    
  97.       $('#MSG').hide();    
  98.       overlay.appendTo(document.body).remove();    
  99.   }    
  100.   
  101.   var imgControl = '<div class="imageControl">\    
  102.                           <a href="javascript:deleteImage(\'||FILENAME||\');">\    
  103.                               <img src="delete.png" />\    
  104.                           </a>\    
  105.                           <img src="Images/||FILENAME||" />\    
  106.                        </div>';    
  107.   //GetFileDetails is used retrieve all the names of the file in the folder "Images"     
  108.   //It also renders the HTML with Images on the server    
  109.   //variable imgControl contains the HTML structure in which the Image is rendered.    
  110.   //Then using for loop, I Replace the text "||FILENAME||" with the actual Image File Name and finally Append it to the div#dropzone    
  111.   function GetFileDetails() {    
  112.       var options = {};    
  113.       options.type = "POST",//Post Method    
  114.       options.url = 'Default.aspx/GetFileList',//URL      
  115.       options.data = '{}',    
  116.       options.async = false,//synchronous Call      
  117.       options.contentType = "application/json; charset=utf-8",    
  118.       options.dataType = "json",    
  119.       options.complete = function (response) { //callback function on completion     
  120.           var resp = JSON.parse(response.responseText);    
  121.           var filesList = JSON.parse(resp.d);    
  122.           var imageControlList = '';    
  123.           for (var i = 0; i < filesList.length; i++) {    
  124.               imageControlList += imgControl.replace('||FILENAME||', filesList[i].File).replace('||FILENAME||', filesList[i].File);    
  125.           }    
  126.           $('#dropzone').html(imageControlList);    
  127.       };    
  128.       $.ajax(options);    
  129.   
  130.   }    
  131.   
  132.   //the function deleteImage is used to delete images    
  133.   function deleteImage(fileName) {    
  134.       var options = {};    
  135.       options.type = "POST",    
  136.       options.url = 'Default.aspx/DeleteImage',    
  137.       options.data = '{ fileName :"' + fileName + '" }',    
  138.       options.async = false,    
  139.       options.contentType = "application/json; charset=utf-8",    
  140.       options.dataType = "json",    
  141.       options.complete = function (response) {    
  142.           GetFileDetails();    
  143.       };    
  144.       $.ajax(options);    
  145.   } 
So here we have finished making a DROPZONE.

Please do not forget to provide your valuable suggestions and feel free to ask queries.
 
That's all for this article, will see you in some other article. Until then, Keep Learning.