MVC .Net Core Drag and Drop File upload with Dropzone JS tutorial

I had a change request come in the other day to add a drag and drop file upload feature to our system as browsing for each file was too time-consuming. This got me thinking about how this would be done in a .Net Core application.

The source code from this article is available on my github page.

Dropzone js

In this tutorial I will be using Dropzone js for the client side implementation, Dropzone is a nice lightweight and easy to use library as you will see below that does not have any dependencies. It is as simple to implement as adding a class name to your form or div element and hooking up the upload action via JavaScript.

In its basic implementation you will get generated thumbnails of the files you upload in a simple styled area. Talking of styling there is a whole page dedicated to how you can theme your dropzone implementation. Dropzone has plenty of options

Getting Started

Using Visual Studio 2019 (community edition is free), create a new ASP.Net Core Web application and select Web Application (Model-View-Controller). Once the project has been generated we will update the home controller to create our new upload page.

public IActionResult Upload()
{
    return View();
}

Create a new view for this by right clicking on Upload() and select “Add View”. Starting with a simple page, one area for users to drag and drop their files.

@{
    ViewBag.Title = "Index";
}

<h2>Drag & Drop file upload </h2>

<div class="row">
	@using (Html.BeginForm("UploadFile", "Home",
						  FormMethod.Post,
						  new
						  {
							  @class = "dropzone",
							  id = "dropzone-form",
						  }))
	{
		<div class="fallback">
			<input name="file" type="file" multiple />
		</div>
	}
</div>

We can easily add Dropzone files to the project by adding it via the new Client-Side-Library manager. See my previous post about libman.

Next, we add the javascript to allow any files dropped in the area to be uploaded to the server. As you can see from the code below we are only allowing images to be uploaded with a limit of 4 files at a time and 20MB maximum size per file. This is all we need to do for our example, but there are plenty of more options you can add to your form if you need.

@section Scripts{
	<script type="text/javascript">
		Dropzone.options.dropzoneForm = {
			paramName: "file",
			maxFilesize: 20,
			maxFiles: 4,
			acceptedFiles: "image/*",
			dictMaxFilesExceeded: "Custom max files msg",
		};
	</script>
}

To upload the files we now need to implement the server side code, in the form HTML helper you can see it is pointing to ‘UploadFiles’ & ‘Home’. UploadFiles will be the name of our method in the Homecontroller. This is where we start to see what changes from a standard .Net application to the new .Net Core application.

Server-side implementation

Previously we would have passed in HttpPostedFileBase to access the file that is being uploaded, however in .Net Core the class HttpPostedFileBase is no longer available. So instead we have to use: IFormFiles class, the other change is how we access folders in the solution. where before we were able to do: Server.MapPath(“~/UploadedFiles”), but as this also isn’t included in .Net Core we instead will use one of the services that’s included by default when you create an ASP.NET Core application, IHostingEnvironment. We can easily add this to our controller by injecting the service:

private IHostingEnvironment _environment;
        
public HomeController(IHostingEnvironment environment)
{
    _environment = environment;
}

By injecting this service we now access the WebRootPath and ContentRootPath properties, the WebRootPath property gets the physical file path to the wwwroot directory in the solution. It is not advisable to store uploaded files to this directory so instead, we will be creating a new folder “Uploads” in our solution and will access it via the ContentRootPath property.

You can see the new Controller action below, as Dropzone js creates a new request for each file being uploaded we only cater for one file in the controller and not a collection. Each image being uploaded is given a new filename (Guid) to avoid handling any overwriting issues.

[HttpPost]
public async Task<IActionResult> UploadFile(IFormFile file)
{
    try
    {
        if (file.Length > 0)
        {
            string folderRoot = Path.Combine(_environment.ContentRootPath, "Uploads");
            string filePath = Guid.NewGuid() + Path.GetExtension(file.FileName);
            filePath = Path.Combine(folderRoot, filePath);
            using (var stream = new FileStream(filePath, FileMode.Create))
            {
                await file.CopyToAsync(stream);
            }
        }
        return Ok(new { success = true, message = "File Uploaded" });
    }
    catch (Exception)
    {
        return BadRequest(new { success = false, message = "Error file failed to upload" });
    }
}

Once you put this all together run the site and navigate to your upload page. Which should look something like the below, now you can drag and drop files onto this region and they will get uploaded to the server. When the file has been uploaded it will display a thumbnail for you.

You can test to see if this has worked by checking in your solution window in Visual Studio. In the uploads folder you will now see the uploaded files with their new Guid names:

That’s it, now you have a fully working file upload drag and drop system using Dropzone and .Net Core.

The source code for this solution is available on my github page.