Uploading files asynchronously in asp.net mvc site
Hi,
I've been looking for quite some time for a complete solution to uploading files in ajax for my site.
For those of you who don't know, browsers won't let you upload files without making a full page reload.
I haven't been able to find a good, working and cross browser solution for this problem.
So after much research and development I have finally managed to solve this problem.
Lets take a look at the following controller.
1. Home
2. UploadImage
The Home action returns a simple view, that you'll see down below, and the UploadImage action is responsible for handling the file uploaded.
This is Index.cshtml:
For comfortable view I've written the css & js inside, but of course it's recommended to split them into different files.
The layout file contains only a reference to jQuery.
I've been looking for quite some time for a complete solution to uploading files in ajax for my site.
For those of you who don't know, browsers won't let you upload files without making a full page reload.
I haven't been able to find a good, working and cross browser solution for this problem.
So after much research and development I have finally managed to solve this problem.
Lets take a look at the following controller.
public class HomeController : Controller { public ActionResult Index() { return View(); } [HttpPost] public ActionResult UploadImage(HttpPostedFileBase image) { try { if (Request.ContentLength > 1024 * 1024 * 2) { return UploadCompanyLogoResult(new { success = false, error = "File size too big. Maximum file size is 2MB." }); } if (Request.Files.Count == 0) { return UploadCompanyLogoResult(new { success = false, error = "Failed uploading file" }); } image = Request.Files[0]; var webImage = new WebImage(image.InputStream) { FileName = image.FileName }; var imageUrl = SaveImageToFile(webImage); return UploadCompanyLogoResult(new { success = true, url = imageUrl }); } catch (Exception e) { Logger.Instance.Error("Failed to upload image", LOG_CATEGORY, e.ToString()); return UploadCompanyLogoResult(new { success = false, error = "Unknown error uploading file" }); } } private string SaveImageToFile(WebImage webImage) { var filePath = Server.MapPath("~/Content/" + webImage.FileName); System.IO.File.WriteAllBytes(filePath, webImage.GetBytes()); return Url.Content("Content/" + webImage.FileName); } private ActionResult UploadCompanyLogoResult(object json) { if (Request.UserAgent.ToLower().Contains("ie")) { var javascriptSerializer = new JavaScriptSerializer(); return Content(string.Format("<pre>{0}</pre>", javascriptSerializer.Serialize(json))); } return Json(json); } }The controller has 2 actions:
1. Home
2. UploadImage
The Home action returns a simple view, that you'll see down below, and the UploadImage action is responsible for handling the file uploaded.
This is Index.cshtml:
For comfortable view I've written the css & js inside, but of course it's recommended to split them into different files.
The layout file contains only a reference to jQuery.
<style type="text/css"> #container { position: relative; display: inline-block; } #container > .loading-circle-container { position: absolute; width: 100%; height: 100%; top: 0; left: 0; text-align: center; background: white; opacity: 0.9; display: none; } #container > .loading-circle-container > .loading_circle { display: inline-block; position: static; background: url('https://pictures.reuters.com/ClientFiles/RTR/Images/ajax-loader.gif') no-repeat; width: 37px; height: 37px; } #container > form { display: inline-block; text-align: center; } #container > form > label { display: block; cursor: pointer; } #container > form > label > #image { cursor: pointer; max-height: 150px; vertical-align: middle; } #container > form > #imageUpload { position: absolute; left: -9999em; } </style> <div id="container"> @using (Html.BeginForm("UploadImage", "Home", FormMethod.Post, new { enctype = "multipart/form-data", target = "upload_file_target" })) { var defaultImage = "https://www.compuchecks.com/BJA/images/logo-placeholder.gif"; <label for="imageUpload" id="button"> <img id="image" src="@defaultImage"> </label> <input type="file" name="imageUpload" id="imageUpload" /> } <div class="loading-circle-container"> <div class="loading_circle"> </div> </div> </div> <script type="text/javascript"> var uploadFileAjax = function (inputTag, successCallback) { var iframe = $('#upload_file_target'); if (iframe.length == 0) { iframe = $('<iframe>').attr({ id: 'upload_file_target', name: 'upload_file_target' }).css({ width: 0, height: 0, border: 0 }).appendTo($('body')); } iframe.load(function () { var iframeContents = iframe[0].contentWindow.document.body.innerHTML; successCallback($(iframeContents).html()); }); inputTag.parent().submit(); } var container = $('#container'); var loader = $('.loading-circle-container', container); var image = $('#image', container).load(function () { loader.fadeOut(); }); var imageUpload = $('#imageUpload', container).on('change', function () { uploadFileAjax(imageUpload, function (responseText) { var responseJson = JSON.parse(responseText); if (responseJson.success) { image.attr('src', responseJson.url); } }); }); $('form', container).on('submit', function () { loader.fadeIn(); }); if ($.browser.mozilla) { $('#button', container).click(function () { imageUpload.click(); }); } </script>You can test the code and see that it actually works (the page doesn't refresh - and the image uploads successfully).
Comments
Post a Comment