MVC Async File Upload

To use the upload html control inside an ajax request, the following steps need to be taken:

  1. Define an ajax function for the upload button
  2. Define the form for the upload
  3. Add the input file control to the form
  4. Handle the file in the MVC controller
  5. Return the json result, wrapped in a text item
  6. Display the results client side, no post back

The file which is uploaded is sent to the controller as a HttpPostedFileBase object. When this file is saved, the result is then sent back to the client and the view is updated.

Controller Logic:

using System;
using System.Collections.Generic;
using System.Web;
using System.Web.Mvc;
using MvcAsyncFilestreamUpload.Models;

namespace MvcAsyncFilestreamUpload.Controllers
{
    public class HomeController : Controller
    {
        public static List<DocumentModel> Docs = new List<DocumentModel>();
 
        public ActionResult Index()
        {
            return View();
        }

        public ActionResult GetFileAsync(int id)
        {
            // get your file from the database async...
            return View();
        }

        public FileUploadJsonResult AjaxUpload(HttpPostedFileBase file, UploadModel model)
        {
            if (file != null && !string.IsNullOrEmpty(file.FileName))
            {
                // here you can save your file to the database...
                var doc = new DocumentModel
                    {
                        Id = Docs.Count+ 1,
                        DocumentName = file.FileName,
                        RecievedDate = DateTime.Now,
                        UploadDate = DateTime.Now
                    };
                Docs.Add(doc);
            }

            if (file == null) return new FileUploadJsonResult { Data = new { message = "FileUploadJsonResultMessage" } };

            return new FileUploadJsonResult { Data = new { message = System.IO.Path.GetFileName(file.FileName) + "FileUploadJsonResultMessageSuccess" } };
        }

        public ActionResult UploadForm()
        {
            var model = new UploadModel();
            model.Documents = Docs;
            // get your file headers from the database

            return PartialView("UploadForm", model);
        }
    }
}

Async form and javascript logic:

@model MvcAsyncFilestreamUpload.Models.UploadModel

<!DOCTYPE html>

<html>
    <head>
        <title>title</title>
        @Scripts.Render("~/bundles/jquery")
        @Scripts.Render("~/bundles/jqueryui")
        @Scripts.Render("~/bundles/jqueryval")
        @Styles.Render("~/Content/themes/base/css")
    </head>
    <body>
        <div>
            A filestream demo
        </div>
        <div id="doclist">
            @Html.Action("UploadForm") 
        </div>
        
        <script type="text/javascript">
            $(document).ready(function () {
                $("#ajaxUploadForm").ajaxForm({
                    target: "#ajaxUploadForm",
                    iframe: true,
                    dataType: "json",
                    beforeSubmit: function () {
                    },
                    success: function (result) {
                        loadUrlContent('@(Url.Action("UploadForm"))', 'doclist');
		            $("#fileInput").replaceWith("<input type=\"file\" id=\"fileInput\" name=\"file\" />");
		        },
		        error: function (xhr, textStatus, errorThrown) {
		        }
		    });
		});
	</script>            
	
	<form id="ajaxUploadForm" action="@Url.Action("AjaxUpload", "Home")" method="post" enctype="multipart/form-data">

		<fieldset class="form">
			<legend>Async Upload Form</legend>
			<ol class="last">
				<li>
					<label>upload </label>
					<input type="file" id="fileInput" name="file" style="width:317px" />
				</li>
				<li>
					<input class="btn" id="ajaxUploadButton" type="submit" value="Upload" />
				</li>
			</ol>
		</fieldset>
	</form> 
    </body>
</html>

FileUploadJsonResult

using System.Web.Mvc;

namespace MvcAsyncFilestreamUpload
{
    public class FileUploadJsonResult : JsonResult
    {
        public override void ExecuteResult(ControllerContext context)
        {
            ContentType = "text/html";
            context.HttpContext.Response.Write("<textarea>");
            base.ExecuteResult(context);
            context.HttpContext.Response.Write("</textarea>");
        }
    }
}

loadUrlContent javascript method:

var loadUrlContent = function (url, containerId, hideErrorMessage, successFunction) {
    $.ajax({
        type: "GET",
        url: url,
        cache: false,
        dataType: 'html',
        success: function (returnData, textStatus) {
            $('#' + containerId).empty().html(returnData);

            if (successFunction) {
                successFunction();
            }
        },
        error: function (XMLHttpRequest, textStatus, errorThrown) {
            if (!hideErrorMessage) {
                alert(textStatus + ': ' + errorThrown);
            }
        }
    });
}

And here the result in the browser (not very nice looking, but it’s only to demonstrate an async upload):
AsyncFileUpload

Full source code: https://github.com/damienbod/MvcAsyncFilestreamUpload

Now all you have to do is save and get your files from a database. This could be implemented using MS SQL Server Filestream.

Links:
http://jquery.com/

http://www.asp.net

http://weblogs.asp.net/bryansampica/archive/2013/01/15/AsyncMVCFileUpload.aspx

http://forums.asp.net/t/1762350.aspx/1

http://thewayofcode.wordpress.com/2012/02/25/drag-and-drop-asynchronous-file-upload-with-html-5-file-api-xmlhttprequest-and-asp-net-mvc-3/

http://blog.filipekberg.se/2013/07/12/are-you-serving-files-insecurely-in-asp-net/

http://www.binaryintellect.net/articles/859d32c8-945d-4e5d-8c89-775388598f62.aspx

http://weblogs.asp.net/bryansampica/archive/2013/01/15/AsyncMVCFileUpload.aspx

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 )

Facebook photo

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

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: