經過搜索得知:因爲SWFUpload是靠Flash進行上傳的,Flash在IE下會把當前頁面的Cookie發到Upload.ashx,但是Chrome、Firefox下則不會把當前頁面的Cookie發到Upload.ashx。因爲Session是靠Cookie中保存的SessionId實現的,這樣由於當前頁面的Cookie不會傳遞給Flash請求的Upload.ashx,因此請求的文件發送到Upload.ashx就是一個新的Session了,當然這個Session就是沒有登錄的了。
解決這個問題的思路也很簡單,那就是手動把SessionId傳遞給服務器,再服務器端讀出SessionId再加載Session。其實解決問題的辦法 SWFUpload的Demo中已經給出了,那就是在SWFUpload的構造函數中設置post_params參數:
swfu = new SWFUpload({
post_params: {
"ASPSESSID": "<%=Session.SessionID %>"
}
post_params中設定的鍵值對將會以Form表單的形式傳遞到Upload.ashx,也就是SWFUpload提供了爲請求增加自定義請求參數的接口。
上面的代碼把當前頁面的SessionId寫到ASPSESSID值中,當用戶上傳文件後,ASPSESSID就會傳遞到服務器上了,在Global.asax的Application_BeginRequest中添加如下代碼:
var Request = HttpContext.Current.Request;
var Response = HttpContext.Current.Response;
try
{
string session_param_name = "ASPSESSID";
string session_cookie_name = "ASP.NET_SESSIONID";
if (HttpContext.Current.Request.Form[session_param_name] != null)
{
UpdateCookie(session_cookie_name, HttpContext.Current.Request.Form[session_param_name]);
}
else if (HttpContext.Current.Request.QueryString[session_param_name] != null)
{
UpdateCookie(session_cookie_name, HttpContext.Current.Request.QueryString[session_param_name]);
}
}
catch (Exception)
{
Response.StatusCode = 500;
Response.Write("Error Initializing Session");
}
其中UpdateCookie方法的定義如下:
static void UpdateCookie(string cookie_name, string cookie_value)
{
HttpCookie cookie = HttpContext.Current.Request.Cookies.Get(cookie_name);
if (cookie == null)
{
cookie = new HttpCookie(cookie_name);
//SWFUpload 的Demo中給的代碼有問題,需要加上cookie.Expires 設置纔可以
cookie.Expires = DateTime.Now.AddYears(1);
HttpContext.Current.Request.Cookies.Add(cookie);
}
cookie.Value = cookie_value;
HttpContext.Current.Request.Cookies.Set(cookie);
}
原理:當用戶請求到達ASP.Net引擎的時候Application_BeginRequest方法首先被調用,在方法中看客戶端是否提交上來了ASPSESSID,如果有的話則把ASPSESSID的值寫入Cookie(以"ASP.NET_SESSIONID"爲Key,因爲ASP.Net中SessionId就是保存在"ASP.NET_SESSIONID"爲Key的Cookie中的),Application_BeginRequest方法後就可以從Cookie中讀取到"ASP.NET_SESSIONID"的值還原出頁面的Session了。
如果網站中還用到了Membership的FormsAuthentication驗證,則還需要把AUTHID也按照SessionID的方法進行處理,這一點是其他講到SWFUpload這個Bug處理的文章中沒有提到的。
在SWFUpload的構造函數中設置post_params參數:
swfu = new SWFUpload({
upload_url: "/AdminHT/UploadArticleImg.ashx",
post_params: {
"ASPSESSID": "<%=Session.SessionID %>",
"AUTHID" : "<%=Request.Cookies[FormsAuthentication.FormsCookieName].Value%>"
},
在在Global.asax的Application_BeginRequest中添加如下代碼:
try
{
string auth_param_name = "AUTHID";
string auth_cookie_name = FormsAuthentication.FormsCookieName;
if (HttpContext.Current.Request.Form[auth_param_name] != null)
{
UpdateCookie(auth_cookie_name, HttpContext.Current.Request.Form[auth_param_name]);
}
else if (HttpContext.Current.Request.QueryString[auth_param_name] != null)
{
UpdateCookie(auth_cookie_name, HttpContext.Current.Request.QueryString[auth_param_name]);
}
}
catch (Exception)
{
Response.StatusCode = 500;
Response.Write("Error Initializing Forms Authentication");
}