Home > ASP.NET MVC, C#, jQuery > Implementing an HTML5 drag & drop based file upload in ASP.NET MVC 3

Implementing an HTML5 drag & drop based file upload in ASP.NET MVC 3

Introduction

HTML5 makes it possible to develop more powerful and more user friendly web applications than we could do ever before. One of the interesting new features is support for drag and drop of files. In the past, if your application needed to provide the possibility to upload files you had to use a file selection chooser. Although this works without issues in all browsers, it is far from user friendly. In native applications, users can interact with files by using drag and drop which is much more intuitive. Luckily for us, HTML5 now also supports this and it is already supported in a number of browsers (Chrome, Firefox, Safari, …).

In this article, I will show you how we can implement drag & drop in an ASP.NET MVC3 web application. We will create a webpage containing a simple drop area that changes of color when the user is dragging a file over the page and we will update the content of the page if the file upload was successful. In order to implement the client side code, we will make use of jQuery and a jQuery plugin called “jquery-filedrop” that simplifies implementing drag & drop based file upload.

You can download “jquery-filedrop” from:
https://github.com/weixiyen/jquery-filedrop

Implementation

We start by creating a new ASP.NET MVC 3 web application and we add the file “jquery-filedrop.js” to the Scripts folder of the project. After this is done we modify the default layout “Views/Shared/_Layout.cshtml” to reference our newly added JavaScript library. In order to do is, add the following line to the head tag.

<script src="@Url.Content("~/Scripts/jquery.filedrop.js")" type="text/javascript"></script>

I also choose to upgrade to the latest version of jQuery with NuGet; but this is not strictly required…

Now that everything is in place, we can start writing our applicative code. First create a HomeController and an “Index” view for this controller.

Solution View

In the view we will create a div with the id “dropZone”. This will be the area in which users can drop files. Next, we will write some jQuery code that will make the div “droppable”. Thanks to the jQuery plugin we are using, the required code for this is trivial. We just have to call the method “filedrop” with a number of needed parameters.

For our sample application, we provide the URL for the file upload, the parameter name of the files to be used in the HTTP POST, the maximum allowed number of files that can be upload simultaneously and we will listen to some events to add some dynamic behavior to the page. More specifically, if the user is dragging a file over the page we will change the color of the drop zone and we will update a list of successfully updated files.

@{
    ViewBag.Title = "Index";
}
<style type="text/css">
    #dropZone {
        background: gray;
        border: black dashed 3px;
        width: 200px;
        padding: 50px;
        text-align: center;
        color: white;
    }
</style>
<script type="text/javascript">
    $(function () {
        $('#dropZone').filedrop({
            url: '@Url.Action("UploadFiles")',
            paramname: 'files',
            maxFiles: 5,
            dragOver: function () {
                $('#dropZone').css('background', 'blue');
            },
            dragLeave: function () {
                $('#dropZone').css('background', 'gray');
            },
            drop: function () {
                $('#dropZone').css('background', 'gray');
            },
            afterAll: function () {
                $('#dropZone').html('The file(s) have been uploaded successfully!');
            },
            uploadFinished: function (i, file, response, time) {
                $('#uploadResult').append('<li>' + file.name + '</li>');
            }
        });
    });
</script>

<h2>File Drag & Drop Upload Demo</h2>
<div id="dropZone">Drop your files here</div>
<br/>
Uploaded Files:
<ul id="uploadResult">

</ul>

Now that the view is in place, we can add the required method to our HomeController in order to support the file upload. I choose to call this method “UploadFiles”, it must have a parameter named files (the one we choose in the configuration of our drop zone) and the parameter must be of type “IEnumerable<HttpPostedFileBase>”. In order to keep things simple, we will just write the files to some temporary folder. But of course you can do whatever you want with the uploaded files…

public class HomeController : Controller
{
    private const string TempPath = @"C:\Temp";

    public ActionResult Index()
    {
        return View();
    }

    [HttpPost]
    public ActionResult UploadFiles(IEnumerable<HttpPostedFileBase> files)
    {
        foreach (HttpPostedFileBase file in files)
        {
            string filePath = Path.Combine(TempPath, file.FileName);
            System.IO.File.WriteAllBytes(filePath, ReadData(file.InputStream));
        }

        return Json("All files have been successfully stored.");
    }

    private byte[] ReadData(Stream stream)
    {
        byte[] buffer = new byte[16 * 1024];

        using (MemoryStream ms = new MemoryStream())
        {
            int read;
            while ((read = stream.Read(buffer, 0, buffer.Length)) > 0)
            {
                ms.Write(buffer, 0, read);
            }

            return ms.ToArray();
        }
    }
}

Conclusion

Now al what rest us, is pressing F5 and testing the application in a browser that already supports this HTML5 specification. I have tested this in the latest version of Google Chrome and Firefox.

image

As I have shown you, it is very easy to implement file drag and drop behavior into your web application, but of course you will still have to support a legacy mechanism as well for people with older browsers.

You can download my sample from:
https://skydrive.live.com/redir?resid=7A3CD9AFBD57E81E!428

Advertisements
Categories: ASP.NET MVC, C#, jQuery
  1. May 30, 2012 at 16:28

    I tried this .. but my uploadFiles action is not receiving any files. The file count = 0. ANy thing do we need to change in config files?

    $(function () {
    $(“#dropZone”).filedrop({
    url: ‘@Url.Action(“UploadFiles”)’,
    paramname: ‘files’,
    maxFiles: 5,
    dragOver: function () {
    $(“#dropZone”).css(‘background’, ‘blue’);
    },
    dragLeave: function () {
    $(“#dropZone”).css(‘background’, ‘gray’);
    },
    drop: function () {
    $(“#dropZone”).css(‘background’, ‘gray’);
    },
    afterAll: function () {
    $(“#dropZone”).html(‘The files have been uploaded successfully’);
    },
    uploadFinished: function (i, file, response, time) {
    $(“#dropZone”).append(” + file.name + ”);
    }
    });
    });

    [HttpPost]
    public ActionResult UploadFiles(IEnumerable files)
    {
    foreach (var file in files)
    {
    string filePath = Path.Combine(TempPath, file.FileName);

    System.IO.File.WriteAllBytes(filePath, ReadData(file.InputStream));
    }

    return Json(“All file uploaded”);
    }

    • May 30, 2012 at 16:34

      Never mind, I got it. Some typo mistakes.

  2. June 22, 2012 at 10:33

    Any idea how to pass another parameter into the action? I.e an integer?
    UploadFiles(IEnumerable files, int ID)
    Thanks

    • December 10, 2013 at 14:12

      public ActionResult UploadFiles(IEnumerable files, int ID)

      and in the view

      url: ‘@Url.Action(“UploadFiles”, “Document”, new { ID= @Model.YourID })’,

  3. Robert
    July 25, 2012 at 23:48

    How do you change the file upload size limit? I tried changing the parameter maxfilesize in the jquery.filedrop.js file from 1 to 10. After attempting to upload a 5mb file I saw these errors in the console of Chrome:

    /Home/UploadFiles 500 (Internal Server Error) jquery.filedrop.js:404:
    —> this.send(ui8a.buffer);

    XMLHttpRequest.sendAsBinary jquery.filedrop.js:404:
    —> this.send(ui8a.buffer);

    $.fn.filedrop.send jquery.filedrop.js:294
    –> xhr.sendAsBinary(builder);

    • pieterderycke
      July 26, 2012 at 09:28

      Yes, I have already changed this parameter. I had no issues doing this. Which code are you using server side? Which version of jQuery are you sing? In which Browser are you having this issue? Are you sure your controller method did not crash?

      • Robert
        July 26, 2012 at 19:18

        Thanks for the reply. I figured it out. I forgot to increase my web.config maxRequestLength setting. Once I did that, it worked great. Thanks!

  4. Bryan
    August 18, 2012 at 20:18

    Hi Pieter, I am taking what you did and wrapping in within an Azure Cloud service with a ASP.net MVC 3 Web Role. Your sample works fine until I enable Access Control Service on my Cloud service. Once I enable that, the files don’t seem to upload. On Azure I’m using Local Storage instead of your C:\temp folder. Can you advise on how I can resolve this issue? Thanks for your help!

    • pieterderycke
      August 19, 2012 at 09:37

      Hello Bryan, I would inspect the HTTP traffic with Fiddler. I suspect that you will have a security issue related to the file upload.

  5. Bryan
    August 19, 2012 at 23:43

    Pieter, thanks. I’m getting an error 500 Internal Server Error on the HTTP post. It states jquery.filedrop.js 404. Are you familiar with Azure Access Control Service? Is there an email address I can reach you at?

    • pieterderycke
      August 20, 2012 at 11:24

      Bryan,

      I would investigate the 404 for jquery.filedrop.js. this is not normal. It is the code that will do the file drag and drop.

  6. jahan
    August 29, 2012 at 10:31

    this is not working with ie9

    • pieterderycke
      August 29, 2012 at 10:45

      No, Internet Explorer 9.0 does not support this.

  7. Danny
    October 7, 2012 at 16:47

    Do you know how I would implement this with form to post data too? So instead of use uploading the files directly I would queue them up and be able to process the files (such as file name, path so I can store the information in a database and then upload them with a submit button?

    • pieterderycke
      October 7, 2012 at 17:46

      yes, this would be possible, but not with with jquery-filedrop plugin. You would have to either use another drag & drop plugin client-side or implement this yourself.

    • Josh
      February 1, 2013 at 01:42

      I needed this exact same functionality. It’s really not too hard — I just bound the .filedrop binding to the onclick event of a folder click (I needed to pass the id of the folder) instead of during the document.ready event. Then I added a data: section that will override the data: section in the default options. It worked like a charm!

  8. akbar
    February 16, 2013 at 21:24

    I am using your sample but want o upload files of larger size. I have tried setting the “maxfilesize” parameter to 20 (20MB) and also used “” under “” tag in web.config file. But even with this, when I drop a file of 4+ MB, nothing happens and no file is uploaded. Is there some other configuration that I am missing?

  9. akbarmunir
    February 16, 2013 at 21:36

    I am using your sample but want to upload files of larger size. I have tried setting the “maxfilesize” parameter to 20 (20MB) and have also set “maxRequestLength” parameter to 20,480 under “httpRuntime” tage under “system.web” in web.config file.

    But even with this, when I drop a file of 4+ MB, nothing happens and no file is uploaded. Is there some other configuration that I am missing?

    • akbarmunir
      February 16, 2013 at 21:57

      Got this working. I was setting the maxRequestLength parameter in wrong file.

      • pieterderycke
        February 17, 2013 at 11:11

        I am glad to hear that you found the fix for your issue 🙂

  10. sravanthi
    April 19, 2013 at 04:01

    how to avoid folders to be uploaded

  11. Jessie
    June 6, 2013 at 07:48

    Hi all,

    I want to get the uploadedPhotoId (auto-generated id, unique Id) after save the data into database. I have tried to modify the coding as below but failed. May I know how can I modify the code?

    HomeController.cs
    —————–
    [HttpPost]
    public ActionResult UploadFiles(IEnumerable files)
    {
    photo Photo = new photo();
    foreach (HttpPostedFileBase file in files)
    {
    string filePath = Path.Combine(TempPath, file.FileName);
    System.IO.File.WriteAllBytes(filePath, ReadData(file.InputStream));
    //save to database.
    Photo.photoName = file.FileName.ToString();
    db.photoyInfo.Add(Photo);
    db.SaveChanges();
    }

    return Json(“All files have been successfully stored.”, id=Photo.uploadedPhotoId, JsonRequestBehaviour.AllowGet);
    }

    Index.cshtml
    —————-

    $(function () {

    $(‘#dropZone’).filedrop({
    url: ‘@Url.Action(“UploadFiles”)’,
    paramname: ‘files’,
    maxFiles: 5,
    dragOver: function () {
    $(‘#dropZone’).css(‘background’, ‘blue’);
    },
    dragLeave: function () {
    $(‘#dropZone’).css(‘background’, ‘gray’);
    },
    drop: function () {
    $(‘#dropZone’).css(‘background’, ‘gray’);
    },
    afterAll: function () {
    $(‘#dropZone’).html(‘The file(s) have been uploaded successfully!’);
    },
    uploadFinished: function (uploadedPhotoId, i, file, response, time) {
    alert(uploadedPhotoId);
    }
    });
    });

    Many thanks.

    Regards,
    Jessie

  12. harsh
    May 31, 2014 at 09:14

    hi,
    I am facing an error (when i opened the firebug console) that “filedrop is not function”.Please le t me know how to resolve it.

  13. insung
    June 18, 2014 at 08:21

    How can I implement the UploadFiles method in asp.net webform?

  14. P Roy
    December 30, 2014 at 10:40

    when I have started to run the application. I drag drop a file but the image file is showing in the browser not uploading. Please help

    • pieterderycke
      January 20, 2015 at 11:39

      you have to drop it in the correct zone of your browser. You also need a browser that supports it. Which browser and version are you using?

  15. k vil
    March 2, 2015 at 17:08

    I am using the latest version of Chrome and ie11….the same result, the image file loads in the browser and doesn’t upload to the folder. What do you mean correct Zone? You drag and drop to the div that says “Drop your files here”

  16. W H
    July 15, 2015 at 22:31

    I am having the same issue. using the latest version of Chrome and ie Version 43.0.2357.134 m .the same result as previous post, the image file loads in the browser and doesn’t upload to the folder.

  17. Haricharan
    September 3, 2015 at 07:35

    hi, Thanks for the solution, its working fine for me but, I’m facing the issue with IE, i have tried to run in IE9 & IE11, indeed its returning , “Browser not supported”, can u fix this?

  18. Rahul Naik
    April 11, 2016 at 14:45

    Hi,
    For every file uploaded there is separate request to controller’s action method, the waht is the use of using IEnumerable as parameter?

  19. Onur
    October 4, 2016 at 07:49

    When i upload a zip file on local, file has damaged and couldn’t unzip.

  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: