ASP.NET Core MVC AJAX File Upload

Uploading files using AJAX and ASP.NET Core MVC could not be simpler. This does not rely upon jQuery. This code allows the uploading of multiple files.

NOTE: The following code examples supports ASP.NET Core. Go to the .NET Framework example if using ASP.NET MVC 5.

To begin, create an ASP.NET Core web application (MVC) in Visual Studio named "Website".

First, the client side. Half the work is done by the function buildFormData().

@{
    Layout = null;
}
<html>
	<head>
	<title></title>
	<script type="text/javascript">
	function createXMLHttp(){
		if(typeof XMLHttpRequest != "undefined"){
			return new XMLHttpRequest();
		} else if(window.ActiveXObject){
			var aVersions = ["MSXML2.XMLHttp.5.0","MSXML2.XMLHttp.4.0","MSXML2.XMLHttp.3.0","MSXML2.XMLHttp","Microsoft.XMLHttp"];
			for(var i = 0; i < aVersions.length; i++){
				try{
					var oXmlHttp = new ActiveXObject(aVersions[i]);
					return oXmlHttp;
				}catch(oError){
					//void
				}
			}
		}
		throw new Error("XMLHttp object could not be created.");
	}
	//used for posting "multipart/form-data"
	function buildFormData(form_object) {
		var fd = new FormData();
		for (var i = 0; i < form_object.elements.length; i++) {
			if (form_object.elements[i].name != null && form_object.elements[i].name != "") {
				if (form_object.elements[i].type == "checkbox") {
					if (form_object.elements[i].checked) {
						fd.append(form_object.elements[i].name, form_object.elements[i].value)
					}
				}
				else if (form_object.elements[i].type == "file") {
					for (var j = 0; j < form_object.elements[i].files.length; j++) {
						fd.append(form_object.elements[i].name,
						form_object.elements[i].files[j],
							form_object.elements[i].files[j].name)
					}
				}
				else {
					fd.append(form_object.elements[i].name, form_object.elements[i].value)
				}
			}
		}
		return fd;
	}
	function submitForm(oform)
	{
		if (window.FormData !== undefined) {
			document.getElementById("SubmitButton").disabled = true;
			var formData = buildFormData(oform);
			var xmlobj = createXMLHttp();
			xmlobj.onreadystatechange = function () {
				if (xmlobj.readyState == 4) {
					if (xmlobj.status == 200) {
						document.getElementById("divResponse").innerHTML = xmlobj.responseText;
						document.getElementById("SubmitButton").disabled = false;
					}
					else {
						throw new Error("Error: " + xmlobj.status + ": " + xmlobj.statusText);
					}
				}
			};
			xmlobj.open("post", oform.action, true);
			xmlobj.send(formData);
		}
		else {
			alert("This browser does not support posting files with HTML5 and AJAX.");
		}
		return false;
	}
	</script>
	</head>
	<body>
	<form onsubmit="return submitForm(this);" method="post" action="/Ajax/UploadFile">
		@Html.AntiForgeryToken()
		<input type="text" required name="fullname" placeholder="enter your name here" /><br />
		<input type="file" accept="image/jpeg" multiple required name="file1" /><br />
		<input type="submit" id="SubmitButton" value="Upload File(s)" />
	</form>
	<div id="divResponse"></div>
	</body>
</html>

Next, the server side. Make a controller named "Ajax" and add the UploadFile() method.

// AjaxController.cs
using System;
using System.IO;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;

namespace Website.Controllers
{
    public class AjaxController : Controller
    {
		private IHostingEnvironment env { get; }

		public AjaxController(IHostingEnvironment env) => this.env = env;

		[HttpPost]
		[ValidateAntiForgeryToken]
		public string UploadFile()
		{
			int i;
			for (i = 0; i < Request.Form.Files.Count; i++)
			{
				if (Request.Form.Files[i].Length > 0)
				{
					if (Request.Form.Files[i].ContentType.ToLower() == "image/jpeg") // this can be changed or omitted
					{
						try
						{
							// make sure that this directory has write permissions
							string file = env.WebRootPath + '\\' + Request.Form.Files[i].FileName;
							using (FileStream fs = new FileStream(file, FileMode.Create, FileAccess.Write))
							{
								const int bufsize = 2048000;
								byte[] buffer = new byte[bufsize];
								using (Stream stream = Request.Form.Files[i].OpenReadStream())
								{
									int b = stream.Read(buffer, 0, bufsize);
										int written = b;
									while (b > 0)
									{
										fs.Write(buffer, 0, b);
										b = stream.Read(buffer, 0, bufsize);
										written += b;
									}
								}
							}
						}
						catch (Exception ex)
						{
							return ex.Message.ToString();
						}
					}
				}
			}
			return i.ToString() + " files copied. Hello, " + Request.Form["fullname"];
		}
    }
}

Tying Up Loose Ends

Finally, make sure that the server will accept large uploads. Edit the Web.config file to have these sections. Note: Visual Studio and ASP.NET Core require creating a web.config file in the root of the project.

<system.webServer>
<security>
	<requestFiltering>
	<requestLimits maxAllowedContentLength="102400000"/>
	</requestFiltering>
</security>
</system.webServer>

It couldn't be any simpler!!!