Introduction
You can see the final result at http://youtu.be/7w0_D0qYVPo.
This is a tutorial about uploading files using drag and drop with ASP.NET MVC by adding the minimum amount of coding.
Background
Drag and drop is a great HTML5 feature, we can leverage it to upload files to the server. This demo simplifies the whole process. However, if you need to customize it, it is important to understand drag and drop in HTML5, and you can add more features to this tool using this link.
Using the Code
In this tip, we will use the library from http://www.dropzonejs.com/ which provides us with basic functionality for dragging and dropping images and other file types directly to the browser.
First, use these files, dropzone.css and dropzone.js and locate them in this location:
~/Scripts/dropzone
Add them to bundle in the BundleConfig.cs which is usually located in the App_Start folder.
bundles.Add(new ScriptBundle("~/bundles/dropzonescripts").Include(
"~/Scripts/dropzone/dropzone.js"));
bundles.Add(new StyleBundle("~/Content/dropzonescss").Include(
"~/Scripts/dropzone/dropzone.css"));
Now go to the Layout and add a style render call in the head
like this @Styles.Render("~/Content/dropzonescss")
and in the end of the body
tag, add this @Scripts.Render("~/bundles/dropzonescripts")
so the simplest layout would be like this:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>@ViewBag.Title</title>
@Styles.Render("~/Content/css")
@Scripts.Render("~/bundles/modernizr")
@Styles.Render("~/Content/dropzonescss")
</head>
<body>
@RenderBody()
@Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/dropzonescripts")
@RenderSection("scripts", required: false)
</body>
</html>
In any controller (should be one controller in the project), we should add the upload action which accepts the uploaded files and saves them to the hard disk and then returns the file identification of the uploaded file (note that in this step, we can save the file to database or to another service). Currently, we will save the file to the folder (~/Images/uploaded) and if does not exist, it will be created. The disadvantage of this approach is (after publishing) that the user of the IIS which is normally IUSER
should have a full permission on that folder.
public ActionResult SaveUploadedFile()
{
bool isSavedSuccessfully = true;
string fName = "";
try
{
foreach (string fileName in Request.Files)
{
HttpPostedFileBase file = Request.Files[fileName];
fName = Guid.NewGuid().ToString(); if (file != null && file.ContentLength > 0)
{
var originalDirectory =
new System.IO.DirectoryInfo(
string.Format("{0}Images\\uploaded", Server.MapPath(@"\")));
string pathString = System.IO.Path.Combine(originalDirectory.ToString(),
"imagepath");
var fileName1 = System.IO.Path.GetFileName(file.FileName);
bool isExists = System.IO.Directory.Exists(pathString);
if (!isExists)
System.IO.Directory.CreateDirectory(pathString);
var path = string.Format("{0}\\{1}", pathString, fName);
file.SaveAs(path);
}
}
}
catch (Exception ex)
{
isSavedSuccessfully = false;
}
if (isSavedSuccessfully == false )
return Json(new { Message = fName });
else
return Json(new { Message = "Error in saving file" });
}
You should add the File Upload Helper class to your project, it accepts a parameter which refers to the URL of the action we have just created:
namespace System.Web.Mvc
{
public static class FileUploadFormHelper
{
public static MvcHtmlString FileUploadForm(this HtmlHelper htmlHelper, string ControllerAction)
{
string formTemplate =
@"<form action='{0}' method='post'
enctype='multipart/form-data' class='dropzone' id='dropzoneForm'>
<div class='fallback'>
<input name='file' type='file' multiple />
<input type='submit' value='Upload' />
</div>
</form>";
return new MvcHtmlString(string.Format(formTemplate, ControllerAction)); ;
}
}
}
Then, in the view that you want to show the uploader, you can use the helper method (Html.FileUploadForm
) and pass to it the location of upload action as a parameter (note that the console.log
raises an exception in Internet Explorer, so you can alert the message instead).
@Html.FileUploadForm("../Home/SaveUploadedFile")
@section scripts{
<script type="text/javascript">
Dropzone.options.dropzoneForm = {
init: function () {
myDropzone = this;
this.on("complete", function (data) {
var res = JSON.parse(data.xhr.responseText);
});
}
};
</script>
}