I came across an article on Tutorialzine which demonstrate file drag and drop upload with jQuery and PHP. As a curious reader, I downloaded the sample files and took a look and also get it running on my LINUX VM. It worked like a charm. But I am a Windows user and .NET programmer, the question is how can I do the same in ASP.NET?
So, to get myself started I used the same downloaded files that I used to check the PHP version of the file drag and drop. The only thing that we are not going to re-use out of these files is the php file. You can delete it if you wish or keep it, it’s of no harm to our ASP.NET app.
Updating The jQuery Part
This example uses an awesome plugin from Weixi Yen and you can found the plugin and it’s sample usage (documentation) on GitHub. The basic or I should say the default functionality provided by this plugin is to allow users to drag and drop the files from desktop to the browser. But before you actually get started with the plugin, I strongly recommend that you make yourself familiar with the parameters and configurations of the plugin.
Open the script.js
file and change the URL to point to the web service or the page which will upload the posted file. Here I want you to pay attention to the javascript function named createImage
. This method accepts the file
as a parameter and returns the image or file data in Base64 format. This is the data which actually gets posted when the user drops a file to the upload area on the web page. This is all up to you whether you want to use a web service or a normal web page to accept the posted file/data. Here is my script.js
file looks like after the changes.
$(function () { var dropbox = $('#dropbox'), message = $('.message', dropbox); dropbox.filedrop({ paramname: 'pic', maxfiles: 5, maxfilesize: 100, //url: '/Uploader.asmx/Upload', url: '/Default.aspx', uploadFinished: function (i, file, response) { $.data(file).addClass('done'); }, error: function (err, file) { switch (err) { case 'BrowserNotSupported': showMessage('Your browser does not support HTML5 file uploads!'); break; case 'TooManyFiles': alert('Too many files! Please select 5 at most! (configurable)'); break; case 'FileTooLarge': alert(file.name + ' is too large! Please upload files up to 2mb (configurable).'); break; default: break; } }, // Called before each upload is started // beforeEach: function (file) { // if (!file.type.match(/^image\//)) { // alert('Only images are allowed!'); // // Returning false will cause the // // file to be rejected // return false; // } // }, uploadStarted: function (i, file, len) { createImage(file); }, progressUpdated: function (i, file, progress) { $.data(file).find('.progress').width(progress); } }); var template = '<div class="preview">' + '<span class="imageHolder">' + '<img />' + '<span class="uploaded"></span>' + '</span>' + '<div class="progressHolder">' + '<div class="progress"></div>' + '</div>' + '</div>'; function createImage(file) { var preview = $(template), image = $('img', preview); var reader = new FileReader(); image.width = 100; image.height = 100; reader.onload = function (e) { // e.target.result holds the DataURL which // can be used as a source of the image: //alert(e.target.result); image.attr('src', e.target.result); }; // Reading the file as a DataURL. When finished, // this will trigger the onload function above: reader.readAsDataURL(file); message.hide(); preview.appendTo(dropbox); // Associating a preview container // with the file, using jQuery's $.data(): $.data(file, preview); } function showMessage(msg) { message.html(msg); } });
Check out line number 10 and 11. I have change the url
parameter to the one where my files are going to be posted. It can be a webservice or just a normal web page. The other two parameters maxfiles
and maxfilesize
defines the number of file that can be uploaded asynchronously and maximum size of the file that can be uploaded in MBs respectively. Also note that the demo that you download from the original source will have a validation that the files that are being uploaded by the user should only be images. If you want to override this rule then uncomment the lines from 33-42. This is it from the jQuery/script part. Now time to move on the server side code.
The Server Side Code
To remind you again that we are posting a file to a web service or to a web page and therefore that code for our web service or on our page will look something like this:
If you are using a web service to upload the posted file:
[WebMethod] [ScriptMethod(ResponseFormat = ResponseFormat.Json)] public string Upload() { HttpContext postedContext = HttpContext.Current; HttpPostedFile file = postedContext.Request.Files[0]; string name = file.FileName; byte[] binaryWriteArray = new byte[file.InputStream.Length]; file.InputStream.Read(binaryWriteArray, 0, (int)file.InputStream.Length); FileStream objfilestream = new FileStream(Server.MapPath("uploads//" + name), FileMode.Create, FileAccess.ReadWrite); objfilestream.Write(binaryWriteArray, 0, binaryWriteArray.Length); objfilestream.Close(); string[][] JaggedArray = new string[1][]; JaggedArray[0] = new string[] { "File was uploaded successfully" }; JavaScriptSerializer js = new JavaScriptSerializer(); string strJSON = js.Serialize(JaggedArray); return strJSON; }
Nothing fancy or complicated in the above code. Remember, the files will send to the web service one by one and not in a collection and this is the reason I am working with one file at a time and not with file collections. In my case I have used a web service that return me JSON result which I can show it to the user, though it is not necessary, but just in case if you want to have one for your web service you need to use 2 using statements:
using System.Web.Script.Serialization; using System.Web.Script.Services;
If you are using a web page to upload the posted file:
HttpContext postedContext = HttpContext.Current; HttpPostedFile file = postedContext.Request.Files[0]; string name = file.FileName; byte[] binaryWriteArray = new byte[file.InputStream.Length]; file.InputStream.Read(binaryWriteArray, 0, (int)file.InputStream.Length); FileStream objfilestream = new FileStream(Server.MapPath("uploads//" + name), FileMode.Create, FileAccess.ReadWrite); objfilestream.Write(binaryWriteArray, 0, binaryWriteArray.Length); objfilestream.Close(); string[][] JaggedArray = new string[1][]; JaggedArray[0] = new string[] { "File was uploaded successfully" }; JavaScriptSerializer js = new JavaScriptSerializer(); string strJSON = js.Serialize(JaggedArray); Response.Write(strJSON); Response.End();
Same code as I have for the web service, put the above code on the page_load event.
Caution!!
While I was working around with the above code and configuration of the plugin I came across an error that won’t allow me to upload heavy files or I should say large files. The error that I received is:
System.Web.HttpException: Maximum request length exceeded
To overcome this error you have make the below configuration in your web.config
file inside <system.web>
<httpRuntime maxRequestLength="102400" executionTimeout="1200" />
A word of caution here, though it will solve your problem but:
- If the
maxrequestLength
is TOO BIG then you will be open to DOS attacks. - The default
executionTimeout
is 360 seconds. Change it accordingly and only if you are running on really slow connections.
This is it, if you have followed the steps above then try uploading some file. And if you haven’t and lazy to put all the pieces together then download the code from the below and try it.
Download: HTML5DragNDrpFileUpload.zip (58.15 kb)