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;
}
Thanks for this post!
ReplyDeleteThis is exactly what I needed. Unfortunately, I need to support IE8+ as well as the more modern browsers. This did the trick without having to use a plugin.
It's good to know that it was of help to you.
Deleteits not working in ie9.
ReplyDeleteIt should work in IE9, not the example with FormData but the work around. Please note that if you are posting JSON by using JSON.stringfy() method then you will need to Json2.js script as IE does not support the method.
ReplyDeleteThank you so much! I've been banging my head against the wall trying to get other solutions to work. The organization I work for requires compatibility with IE8. Your solution was the only one that worked for me.
ReplyDeleteGood to know, thanks for your feedback. I try to post on stuff, that I myself have faced issues solving, I hope it helps more and more people.
DeleteThis looks promising (have to try it out but looks like it will work). Most of the sites I encountered in my search used HTML5 features which do not help me considering I have to support a website on older IE versions.
ReplyDeleteThank you for your post.
I'm having trouble in IE8. I have to click the Upload button 3 times to get the form to submit. Have you run into this?
ReplyDeleteSorry Anon I did not run into any such issues. Either it will work or it will not. You can try updating to the latest stable version of jquery that you might be using.
DeleteDear KAUSHIK,
ReplyDeleteCan you share the project? I am new to JQuery & MVC.
Dear abdul, I do not have a project as such specifically created for this, but I will try and see if I can post something on github. I have never used github, but I believe sharing is possible through that. Sorry I did not reply earlier as I was down with fever.
ReplyDeleteDear KAUSHIK,
ReplyDeleteThanks for consideration. Get Well Soon.
This comment has been removed by the author.
ReplyDeleteDear KAUSHIK,
ReplyDeleteThanks a lot. As good as it gets. btw there may be wrong id of frame for unbind in code snippet.
Thanks for the correction, I have updated the post. Appreciate it
DeleteHello KAUSHIK, the example works in cross domain?
ReplyDeleteShould work if the browser allows it otherwise you will have to use some kind of proxy on your present domain and route that from the server side.
DeleteHi Kaushik,
ReplyDeleteThanks for the nice example. It does work on the controller side for me in I.E 9.0 but two issues.
1) It wont come back into the javascript post controller processing. I need to close a dialog and run some jquery function on the success of form posting.
if (successFunction) -- Doesnt fire (also where is this boolean var)
2) I.E open another tab on form submit, is this avoidable
thanks.
appreciate any help.
Manish Jadhav
manish,
DeleteIn the example if you closely notice, it actually does not post back the form but the iframe is made the target, so it will post back the iframe so the page will not reload. See the line below
document.getElementById('my_form').target = 'my_iframe';
I hope this clarifies.
javascript runtime error access is denied error occured
ReplyDeletewhile uploading file IE 9
code from KAUSHIK GHOSH is not checking for error codes, even if 400 Bad Request is returned by server, 'successFunction' will be invoked. In case error is returned by server and size is less than 512 bytes, then you have troubles with IE for accessing the iframe content (see https://blogs.msdn.microsoft.com/ieinternals/2010/08/18/friendly-http-error-pages/ )
DeleteOther browser working fine
ReplyDeleteplease help me to resolve above error
ReplyDeleteMake sure your controller action is accepting post properly and also the file that you are trying to upload is accessible.
DeleteThanks man...
ReplyDelete