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.
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.
You can test the code and see that it actually works (the page doesn't refresh - and the image uploads successfully).
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 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
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); } } |
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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
<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" })) { <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> |
Comments
Post a Comment