- Uploadify flash upload button is ugly so we use CSS to make it invisible and fake an HTML button under it.
- The Uploadify flash upload doesn't pass the ASP.NET session and authentication cookies naturally, which we want for recognition and authorization, so we handle that.
UPLOADIFY FILES
Put all Uploadify files in a project folder called ClientScript/uploadify
SCRIPT
Put this code on the regular View page that performs the upload.
<script type="text/javascript" src="<%= Url.Content("~/ClientScript/jquery-1.4.2.min.js") %>"></script>
<script type="text/javascript" src="<%= Url.Content("~/ClientScript/uploadify/swfobject.js") %>"></script>
<script type="text/javascript" src="<%= Url.Content("~/ClientScript/uploadify/jquery.uploadify.v2.1.4.min.js") %>"></script>
<script type="text/javascript">
$(function () {
// Uploadify File Upload System
// SessionSync data is sent in scriptData for security reasons, see UploadifySessionSync() in global.asax
var UploadifyAuthCookie = '<% = Request.Cookies[FormsAuthentication.FormsCookieName] == null ? string.Empty : Request.Cookies[FormsAuthentication.FormsCookieName].Value %>';
var UploadifySessionId = '<%= Session.SessionID %>';
$("#fuFileUploader").uploadify({
'hideButton' : true, // We use a trick below to overlay a fake html upload button with this hidden flash button
'wmode' : 'transparent',
'uploader': '<%= Url.Content("~/ClientScript/uploadify/uploadify.swf") %>',
'cancelImg': '<%= Url.Content("~/ClientScript/uploadify/cancel.png") %>',
'buttonText': 'Upload File',
'script': '<%= Url.Action("FileUpload", "Media") %>',
'multi': true,
'auto': true,
'scriptData' : { RequireUploadifySessionSync: true, SecurityToken: UploadifyAuthCookie, SessionId: UploadifySessionId },
'onComplete' : function (event, ID, fileObj, response, data)
{
response = $.parseJSON(response);
if (response.Status == 'OK')
{
// Put your own handler code here instead of the following...
alert('File Uploaded OK!');
}
}
});
});
</script>
HTML
Put this HTML on the same View as the script above.
<div style="position: relative;">
<input type="button" id="btnUpload" value="Upload File" />
<div style="position: absolute; top: 4px; left: 3px;">
<input id="fuFileUploader" name="file_upload" type="file" />
</div>
</div>
GLOBAL.ASAX
Add the following bits.
protected void Application_BeginRequest(Object sender, EventArgs e)
{
if (HttpContext.Current.Request["RequireUploadifySessionSync"] != null)
UploadifySessionSync();
}
/// <summary>
/// Uploadify uses a Flash object to upload files. This method retrieves and hydrates Auth and Session objects when the Uploadify Flash is calling.
/// </summary>
/// <remarks>
/// Kudos: http://geekswithblogs.net/apopovsky/archive/2009/05/06/working-around-flash-cookie-bug-in-asp.net-mvc.aspx
/// More kudos: http://stackoverflow.com/questions/1729179/uploadify-session-and-authentication-with-asp-net-mvc
/// </remarks>
protected void UploadifySessionSync()
{
try
{
string session_param_name = "SessionId";
string session_cookie_name = "ASP.NET_SessionId";
if (HttpContext.Current.Request[session_param_name] != null)
UploadifyUpdateCookie(session_cookie_name, HttpContext.Current.Request.Form[session_param_name]);
}
catch {}
try
{
string auth_param_name = "SecurityToken";
string auth_cookie_name = FormsAuthentication.FormsCookieName;
if (HttpContext.Current.Request[auth_param_name] != null)
UploadifyUpdateCookie(auth_cookie_name, HttpContext.Current.Request.Form[auth_param_name]);
}
catch {}
}
private void UploadifyUpdateCookie(string cookie_name, string cookie_value)
{
HttpCookie cookie = HttpContext.Current.Request.Cookies.Get(cookie_name);
if (cookie == null)
cookie = new HttpCookie(cookie_name);
cookie.Value = cookie_value;
HttpContext.Current.Request.Cookies.Set(cookie);
}
Models/MediaAssetUploadModel.cs
public class MediaAssetUploadModel
{
public HttpPostedFileBase fileData { get; set; }
public string SecurityToken { get; set; }
public string Filename { get; set; }
}
Controllers/MediaController.cs
[Authorize]
public ActionResult FileUpload(MediaAssetUploadModel uploadedFileMeta)
{
string fullFilePath = SaveUploadedFile(uploadedFileMeta);
//TODO: Error handling
return Json(new { Status = "OK" });
}
//TODO: move this into a manager/repository class
private string SaveUploadedFile(MediaAssetUploadModel uploadedFileMeta)
{
string fileName = Guid.NewGuid() + System.IO.Path.GetExtension(uploadedFileMeta.Filename);
string fullSavePath = Path.Combine(ConfigurationManager.AppSettings["MediaAssetFolder"], fileName);
uploadedFileMeta.fileData.SaveAs(fullSavePath);
return fullSavePath;
}
Web.config
Make following changes to upload files to c:\temp , with a max file size of 100Mb.
Change these to suit yourself - c:\temp will get automatically cleared so you have been warned.
If you create your own upload folder, remember you will need to give write perms to the ASP.NET process.
<configuration>
<appSettings>
<add key="MediaAssetFolder" value="c:\temp"/>
</appSettings>
<system.web>
<httpRuntime maxRequestLength="100000" />
</system.web>
</configuration>
Thanks for posting this - the write up was spot on. You saved me an enormous amount of time piecing this all together.
ReplyDeleteGreat tip. Took me all of 2 minutes from start to finish and now my MVC 2 has async file uploads.
ReplyDeleteThank you!
Oh I wish this post had been around a few months ago!! This has to be the most complete coverage around of how to get Uploadify and MVC2 to play nice together. Really great stuff. Thanks so much for this.
ReplyDeletewe tried, but it is not working... dont know why?
ReplyDeleteAfter some small modifications to accomodate Razor and to save images direct to a database, this worked a treat.. Thanks very much!
ReplyDeleteGreat post! Is this solution ajax based? Or does it cause the page to refresh?
ReplyDeleteThanks,
Calum
Yeah, Uploadify does the upload asynchronously and calls the 'onComplete' javascript function as seen in the code above. You can then hook in any other AJAX / jQuery magic you like to handle the completion event.
ReplyDeleteNo nasty refreshes! :D
Cheers James, good to know... My page kept refreshing must of not copied and pastied your project well enough :)
ReplyDeleteThe value for Request.Cookies[FormsAuthentication.FormsCookieName] always seems to be null, so the controller is never called when the [authorize] tag is applied. Do I have to set something in the web.config for this cookie to be written? Thanks
ReplyDeleteHmm, have you put breakpoints into global.asax to make sure uploadify is sending through the scriptdata correctly?
ReplyDeleteSpecifically, is HttpContext.Current.Request["RequireUploadifySessionSync"] being set in Application_BeginRequest?
Also, Firebug/Fiddler is your friend - check the cookies coming in and out.
Congratulations the code to fix the session lost it works very good, thank you
ReplyDeleteAnyway of getting this javascript in a separate file?
ReplyDeleteI hope you are as good a Daddy as you are at Code, this is so helpful! :)
ReplyDeleteI did have some questions though, hopefully you are still taking responses to this post. I was curious as to why the security tokens, cookies, etc. I am not an expert programmer, and I am learning, but I wanted to know why that was needed to upload images?
I plan on using this code to upload images to a web server, store the image paths in a database, and use them in a slideshow on a public website. Are there any caveats I need to be aware of that aren't listed here? Thanks for your time!
Dear James,
ReplyDeleteWhen i used the uploadify on ajax/jquery dialog i can't use html button instead of flash upload button.
Hi, maybe you can help me, I am using same code, but after some time the page have been loaded, upoloadify uses new session(comparing "HttpContext.Session.SessionID" in controller and "ASP.NET_SessionId" in cookie)
ReplyDeleteAny ideas? Can I invoke old session with older id in controller?
You are a hero, thanks for the good post
ReplyDeleteHi, I'm having troubles getting this to work with Windows Authentication and MVC3, I'm still getting the same old "HTTP Error" before it even hits my action...
ReplyDeleteI would really appreciate help on this please!
Thanks.. This is it.. Daddycode!.
ReplyDeletei keep getting http error ...
ReplyDeleteneed help
cool its working now
ReplyDelete