ASP.NET web applications that require uploading files from the client machine to the server use the file field to select files. The selected files are uploaded to the server using form submission techniques. In addition to the file field, HTML5 also allows you to select files using drag and drop. Using this feature you can drag files from Windows Explorer or Desktop and drop them on a predefined area of a web page. The files can then be uploaded to the server. This article illustrates how the HTML5 drag and drop feature can be used to upload files on the server.
Traditionally you use the HTML file field to select files that are to be uploaded to the server. ASP.NET web forms wrap the file field into the FileUpload server control and ASP.NET MVC applications can use an <input> element with type attribute set to file. Another alternative offered by HTML5 is dragging one or more files from Windows Explorer or Desktop and drop them onto some predefined HTML element of a web page. You can then access the dropped files using the dataTransfer object available to drag and drop events.
To understand how files can be selected using the drag and drop features of HTML5, let's develop a new ASP.NET web forms application. The HTML markup of the default web form is shown below:
<form id="form1" runat="server">
<center>
<div id="box">Drag & Drop files from your machine on this box.</div>
<br />
<input id="upload" type="button" value="Upload Selected Files" />
</center>
</form>
As you can see, the <form> consists of a <div> element and a button. The <div> element is intended to drop the files dragged from the local machine. Merely dropping the files won't upload them to the server. Clicking on the button initiates the file upload operation.
To handle the file drop operation you need to wire certain event handlers to the box <div> element. The following jQuery code shows how that can be done:
var selectedFiles;
$(document).ready(function () {
var box;
box = document.getElementById("box");
box.addEventListener("dragenter", OnDragEnter, false);
box.addEventListener("dragover", OnDragOver, false);
box.addEventListener("drop", OnDrop, false);
...
}
The code declares a global variable named selectedFiles for storing a list of selected files. The ready() function wires three event handler functions to the respective events of the box <div> element, viz. dragenter, dragover and drop using addEventListener() method. The first parameter of the addEventListener() method is the event name and the second parameter is the event handler function. The event handler functions are shown below:
function OnDragEnter(e) {
e.stopPropagation();
e.preventDefault();
}
function OnDragOver(e) {
e.stopPropagation();
e.preventDefault();
}
function OnDrop(e) {
e.stopPropagation();
e.preventDefault();
selectedFiles = e.dataTransfer.files;
$("#box").text(selectedFiles.length + " file(s) selected for uploading!");
}
The OnDragEnter() and OnDragOver() event handler functions are simple and they merely prevent the event bubbling of the respective events. The OnDrop() function is important since it handles the drop event. The list of files dragged and dropped on the <div> element is obtained using the files property of the dataTransfer object. The files object is of type FileList and each item of the FileList collection is of type File. These two objects are available as a part of the HTML5 File API. The OnDrop() function stores the selected files in the global variable - selectedFiles and displays a message in the <div> using the text() method that indicates the number of files selected. The following figure shows how the default web form looks after dragging and dropping files on the <div> element.
Default web form after dragging and dropping files to the <div> element
How to Send Files to the Servere?
To send the selected files from the client to the server you can use different techniques but in this example you will use jQuery $.ajax() method for uploading the files. The following code shows how $.ajax() method can be used for this purpose.
$("#upload").click(function () {
var data = new FormData();
for (var i = 0; i < selectedFiles.length; i++) {
data.append(selectedFiles[i].name, selectedFiles[i]);
}
$.ajax({
type: "POST",
url: "FileHandler.ashx",
contentType: false,
processData: false,
data: data,
success: function (result) {
alert(result);
},
error: function () {
alert("There was error uploading files!");
}
});
});
The code shown above first creates a FormData object. The FormData object encapsulates form's data that you wish to send to the server. All the selected files are added to the FormData object using its append() method. The first parameter of the append() method is the name of the file being added and the second parameter is the File object itself. Once the FormData object is ready you make a POST request to a Generic ASP.NET Handler (FileHandler.ashx) using jQuery $.ajax() method. You will create the generic handler in the next section.
The type of the request is POST. The url is FileHandler.ashx. Notice that the processData option is set to false. By default when you use the $.ajax() method the data is sent in URL encoded format. To prevent this behavior processData is set to false. The data option is set to the FormData object created earlier. The success function simply displays the message returned by the generic handler. The error handler function displays an error message in case there is any error while calling FileHandler.ashx.
Receive the Uploaded Files
The ASP.NET generic handler - FileHandler.ashx - receives the files sent by the $.ajax() method. The generic handler also saves them to a folder on the server. The following code shows how the handler accomplishes this task:
public void ProcessRequest(HttpContext context)
{
if (context.Request.Files.Count > 0)
{
HttpFileCollection files = context.Request.Files;
foreach (string key in files)
{
HttpPostedFile file = files[key];
string fileName = file.FileName;
fileName = context.Server.MapPath("~/uploads/" + fileName);
file.SaveAs(fileName);
}
}
context.Response.ContentType = "text/plain";
context.Response.Write("File(s) uploaded successfully!");
}
The ProcessRequest() method of the FileHandler.ashx is called when the files are sent to the server using the $.ajax() method. The uploaded files can be accessed using the Files collection of the Request object. Each item inside the Files collection is of type HttpPostedFile. A foreach loop iterates through all the files from the Files collection and saves the individual file using the SaveAs() method of HttpPostedFile class. Once all files are saved a success message is sent to the client.
Note that by default ASP.NET sets request length to 4096 bytes. If you wish to upload large files you may adjust the request length using web.config file as shown below:
<httpRuntime
maxRequestLength="20000"
requestValidationMode="4.5"
targetFramework="4.5"
encoderType="..." />
As you can see the maxRequestLength attribute of the <httpRuntime> section is set to 20000 bytes. You need to adjust this value as per your requirement.
That's it! You can now run the web form, drag and drop files on the <div> element and click on the "Upload Selected Files" button to upload them on the server.