HTML5 Native Drag And Drop File Upload
Thanks to the new drag and drop and file API features of HTML5 creating a drag and drop file upload has become much easier. Sadly it isn’t widely supported by the browsers yet as it’s currently just supported in Firefox 4+, Chrome and Opera 11.10+. But since this blog is all about new web technologies we don’t care about that.
Step 1. Create the Layout
So lets get started, start Visual Studio and create an ASP.NET Empty Web Application, add a web form named “Default.aspx” and add the following HTML.
<!DOCTYPE html>
<html>
<head runat="server">
<title>Drag n' Drop File Upload</title>
<link href="/Style.css" rel="Stylesheet" />
<script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.6.1.min.js"></script>
<script>
</script>
</head>
<body>
<form id="form1" runat="server">
<div id="dropZone">
Drop File Here to Upload.
</div>
</form>
</body>
</html>
This is basic, so I won’t explain it for you, all you need to know is that the “dropZone” div is the area where we will allow the user to drop their files.
And this is our CSS:
body
{
font: 12px Arial;
}
#dropZone
{
border-radius: 5px;
border: 2px solid #ccc;
background-color: #eee;
width: 250px;
padding: 50px 0;
text-align: center;
font-size: 18px;
color: #555;
margin: 50px auto;
}
#dropZone.hover
{
border-color: #aaa;
background-color: #ddd;
}
#dropZone.error
{
border-color: #f00;
background-color: #faa;
}
Also quite basic, just some CSS to render our dropZone and two CSS classes for when dragging and showing errors.
Step 2. Write The Client Side Upload Script
Now we get to the interesting parts, the upload script. We start of by adding a dropZone variable to save our element and a document ready event inside the empty script tags. Inside we reference our dropZone div tag and remove any previous errors.
var dropZone;
$(document).ready(function () {
dropZone = $('#dropZone');
dropZone.removeClass('error');
}
Next we need to check if the browser supports the HTML5 file API. We do that by checking if the FileReader function is set, if it’s not set it means that the browser won’t support the file API. In this tutorial we’ll just show the user an error message, but it might be a good idea to add a fallback solution using a regular input field instead.
// Check if window.FileReader exists to make
// sure the browser supports file uploads
if (typeof(window.FileReader) == 'undefined') {
dropZone.text('Browser Not Supported!');
dropZone.addClass('error');
return;
}
Next we’ll add two events to our dropZone, “ondragover” and “ondragend”, as their names say “ondragover” triggers when the user drags a file over our dropZone and “ondragend” triggers when the user stops dragging the file. Since jQuery objects doesn’t support these events we need to get the regular JavaScript object, this is done by adding “[0]” after your jQuery object. In these events we’ll just change the CSS class of our dropZone.
// Add a nice drag effect
dropZone[0].ondragover = function() {
dropZone.addClass('hover');
return false;
};
// Remove the drag effect when stopping our drag
dropZone[0].ondragend = function() {
dropZone.removeClass('hover');
return false;
};
Now it’s time for the “ondrop” event, this is where all the magic happens. The default event for dragging a file into a web browser window is to show it, we need to stop the browser from doing this, adding event.preventDefault will stop the browser from doing this.
Tip
event.preventDefault can be used on any event to stop the browser from executing the default event.
Next we just remove the hover CSS since the user has dropped the file.
// The drop event handles the file sending
dropZone[0].ondrop = function(event) {
// Stop the browser from opening the file in the window
event.preventDefault();
dropZone.removeClass('hover');
}
Still in the “ondrop” event we need to get the dropped file and validate its file size, we don’t want the user to upload a larger file than the maxRequestLength specified in web.config since it will result in an ugly server error, we will add maxRequestLength property to our code behind later on which we print out into our if statement in our ASPX. The rest is quite straight forward.
var file = event.dataTransfer.files[0];
// Validate file size
if(file.size > <%=maxRequestLength%>) {
dropZone.text('File Too Large!');
dropZone.addClass('error');
return false;
}
Now it’s time to write the AJAX request, since sending files to ASP.NET is tricky in jQuery we’ll use the good ol’ XMLHttpRequest. We start of by creating the XMLHttpRequest object and add two events to show upload progress and result. Next we set the target URL and the file name in the request header, lastly we call the send function with our file as input parameter.
var xhr = new XMLHttpRequest();
xhr.upload.addEventListener('progress', uploadProgress, false);
xhr.onreadystatechange = stateChange;
xhr.open('POST', '/Default.aspx', true);
xhr.setRequestHeader('X-FILE-NAME', file.name);
xhr.send(file);
The last thing we need to do before writing the server code is to add the “progress” and “onreadystatechange” events. The “uploadProgress” function is quite simple, it just calculates the how of the file which has been sent to the server and shows the upload progress to the user.
The “stateChange” function waits until “readyState” is “4″ which means that the request is finished. If the HTTP status is 200 it means that the upload finished OK, otherwise we’ll show an error message to the user.
// Show the upload progress
function uploadProgress(event) {
var percent = parseInt(event.loaded / event.total * 100);
$('#dropZone').text('Uploading: ' + percent + '%');
}
// Show upload complete or upload failed depending on result
function stateChange(event) {
if (event.target.readyState == 4) {
if (event.target.status == 200) {
$('#dropZone').text('Upload Complete!');
}
else {
dropZone.text('Upload Failed!');
dropZone.addClass('error');
}
}
}
Step 3. Write the Server Side Code
Add a folder named “Uploads” inside your solution root, we will place all the uploads inside this folder.
Next we write the maxRequestLength property which is used by our JavaScript to validate the file size. We’ll try to get the HttpRuntimeSection and read the MaxRequestLength from our web.config, the MaxRequestLength is the max allowed size in kB of the request made to the server. If we don’t find it we’ll return the default value. Since the file.size in our JavaScript returns the size in bytes we need to multiply our MaxRequestLength by 1024.
/// <summary>
/// The max file size in bytes
/// </summary>
protected int maxRequestLength
{
get
{
HttpRuntimeSection section =
ConfigurationManager.GetSection("system.web/httpRuntime")
as HttpRuntimeSection;
if (section != null)
return section.MaxRequestLength * 1024; // Cofig Value
else
return 4096 * 1024; // Default Value
}
}
Tip
You can increase the max upload file size by setting <httpRuntime maxRequestLength=”SizeInBytes” /> inside <system.web> in your web.config.
Next we need to write our file receiver, we start off by checking if the “X-File-Name” request header is set, if it is set it means that we have received a file. We get the file contents using to a Stream using Request.InputStream and then we copy it to a file stream which will write the file to our server.
/// <summary>
/// Checks if a file is sent to the server
/// and saves it to the Uploads folder.
/// </summary>
private void handleFileUpload()
{
if (!string.IsNullOrEmpty(Request.Headers["X-File-Name"]))
{
string path = Server.MapPath(string.Format("~/Uploads/{0}",
Request.Headers["X-File-Name"]));
Stream inputStream = Request.InputStream;
FileStream fileStream = new FileStream(path, FileMode.OpenOrCreate);
inputStream.CopyTo(fileStream);
fileStream.Close();
}
}
Now we just need to make sure our handleFileUpload is executed, add a call to the function in your page load event.
/// <summary>
/// Page Load
/// </summary>
protected void Page_Load(object sender, EventArgs e)
{
handleFileUpload();
}
That’s it, now you should have a working drag and drop file upload.
Download
Download the source from here: Download
I like the design of your resource! It looks really awesome.
Nice article and can I know how to drop multiple files and display them after uploading?Can you please help me out this issue.
I haven’t tried creating a multiple file upload myself, I might check it out and write an article about it.
Thanks for your reply and that will b a great help if you can do it!
Does IE9 support Drag & Drop upload?
No, sadly it doesn’t. I haven’t tried it on the IE10 platform preview though Microsoft might have added it there.
Its really awesome
This is very interesting, will be very useful once IE supports it.
In case anyone is interested, to handle multiple files you just need to loop through the dataTransfer.files array;
// The drop event handles the file sending
dropZone[0].ondrop = function(event) {
// Stop the browser from opening the file in the window
event.preventDefault();
dropZone.removeClass(‘hover’);
// Get the file and the file reader
var files = event.dataTransfer.files;
$(files).each(function() {
var file = this;
// Validate file size
if(file.size > ) {
dropZone.text(‘File Too Large!’);
dropZone.addClass(‘error’);
return false;
}
// Send the file
var xhr = new XMLHttpRequest();
xhr.upload.addEventListener(‘progress’, uploadProgress, false);
xhr.onreadystatechange = stateChange;
xhr.open(‘POST’, ‘/Default.aspx’, true);
xhr.setRequestHeader(‘X-FILE-NAME’, file.name);
xhr.send(file);
});
};
Would be interesting to see if it can handle folders too.
Lars, I like your drag-drop article. I’d like to talk to you about your article. No, I’m not someone seeking free support and I’m not a headhunter either.
Wally
Wally, you’re welcome to contact me on the email provided at the contact page.
Are files actually being uploaded? I tried it but files not copied to Uploads folder.
Thanks
vikas, they should be uploaded. Make sure the IIS has write permissions to the folder. Also, try debugging it with Visual Studio to see if you get any errors.
This is a good tutorial, I will use this for my on-work website admin panel
I don’t see the file uploaded. When I drag and drop to browser, it downloads back to my client machine. Running on a macbook with chrome.
how big of a file can one upload.
I tried 300mb and 1gb and neither works.
I updated web.config to reflect sizes.
it gets to 99% then it fails.
felipe, it should work in the same way as regular file uploads, make sure the maxRequestLength in web.config is enough and that the executionTimeout isn’t too short.
Do you get any ASP.NET exceptions or something like that?
Hi
That was exactly what I was searching for. I am using IE9. I downloaded your solution and tried to run in VS 2010 but it says browser not supported. Can you help?
Thanks
Sap
Hi Sap, Sorry but this solution won’t work in IE9 as it doesn’t support the required FileReader class to open and read the file.
You have to do something using Flash etc. to make it work in IE.