File Upload in ASP.NET MVC via ajax
Problem
While looking for fileupload options via ajax and without posting the whole form, we often come across code in the internet using FormData API, which works perfectly fine on chrome and mozilla but on on IE. so a code snippet using a FormData API would like this below
//View Code
<script type="text/javascript">
function save() {
$("#test").submit();
}
function submitForm() {
var formData = new FormData($('#test')[0]);
$.ajax({
url: '@Url.Action("Upload"," FileUpload")',
type: 'POST',
data: formData,
async: false,
success: function (data) {
alert('posted')
},
cache: false,
contentType: false,
processData: false
});
return false;
}
</script>
<h2>Index</h2>
<input type="button" value="Submit" onclick="save();" />
<form id="test" action="javascript:submitForm( );" method="post" enctype = "multipart/form-data">
<div>
<label for="fileUpload">File upload</label>
<input type="file" id="fileUpload" name="fileUpload" />
</div>
</form>
//Controller Code
public ActionResult Upload()
{
HttpPostedFileBase postedFile = Request.Files[0];
return View();
}
The above snipped works fine on chrome and mozilla and you will be able to see the postedFile in the controller but it does not work on IE because most versions of IE does not support FormData.
Solution
So the solution I came up with after going some recommendations over internet about HTML controls on different browsers is that its better to use iframes. So Idea is to point the target of the form to an iframe and even bind a load event to the iframe so that you know when the upload is finished and write additional jquery functions. Also you can even hide the iframe and not show the user. But this solution works on IE as well. The code is as below
The code also shows how to post additional data along with the file post.
@{
ViewBag.Title = "Index";
}
<script src="~/scripts/jquery-1.9.1.min_.js"></script>
<script type="text/javascript">
function successFunction() {
alert($('#my_iframe').contents().find('p').html());
}
function redirect() {
//debugger;
document.getElementById('my_form').target = 'my_iframe'; //'my_iframe' is the name of the iframe
//document.getElementById('my_form').submit();
var callback = function () {
if (successFunction)
successFunction();
$('#my_iframe').unbind('load', callback);
};
$('#my_iframe').bind('load', callback);
$('#hfParam').val('id:1');
$('#my_form').submit();
//$("#my_form").trigger("submit");
}
</script>
<h2>Index</h2>
<input type="button" name="action" value="Upload" onclick="redirect();"/>
<form id="my_form" name="my_form" action="/FileUpload/UploadFile" method="POST" enctype="multipart/form-data" >
<div id="main">
<input name="my_hidden" id="hfParam" type="hidden" />
<input name="my_files" id="my_file" type="file" />
<iframe id='my_iframe' name='my_iframe' src="">
</iframe>
<div id="someDiv"></div>
</div>
</form>
[HttpPost]
public ActionResult UploadFile()
{
ContentResult result = new ContentResult() { Content = "<p></p>", ContentType = "text/html"};
HttpPostedFileBase postedFile = Request.Files[0];
try
{
result.Content = "<p>" + postedFile.FileName + "</p>";
}
catch (System.Exception ex)
{
result.Content = ex.Message;
}
return result;
}