1. 程式人生 > >關於 SWFUpload 在firefox (ff,火狐)下,報錯 302,session,cookie

關於 SWFUpload 在firefox (ff,火狐)下,報錯 302,session,cookie


最近在處理多檔案上傳問題,一直以來都是用jquery的MultiFile.js外掛,但是由於該外掛不能顯示進度條的緣故,而專案實際上對進度條必不可少

再加上實在是不願意花時間去寫檔案上傳進度,只得在網上找到了swfupload用flash上傳檔案的外掛,在IE下上傳多檔案十分順利,但是在火狐下

卻總是報302錯誤,通過千百度,驀然回首到谷歌折騰了番,才瞭解了原因,謹以此篇小計下來,畢竟上傳帶進度條的功能實在是太常見了,先收

著。

        因為SWFUpload是靠Flash進行上傳的,Flash在IE下會把當前頁面的Cookie發到Upload.aspx,但是Chrome、Firefox下則不會把當前頁面的Cookie發到Upload.aspx。

因為Session是靠Cookie中儲存的SessionId實現的,這樣由於當前頁面的Cookie不會傳遞給Flash請求的Upload.aspx,因此請求的檔案傳送到Upload.ashx就是一個新的Session了,當然這個Session就是沒有登入的了。    

     解決這個問題的思路也很簡單,那就是手動把SessionId傳遞給伺服器,再伺服器端讀出SessionId再載入Session。其實解決問題的辦法SWFUpload的Demo中已經給出了,那就是在SWFUpload的建構函式中設定post_params引數:

swfu = new SWFUpload({
                    // Backend Settings
                    upload_url: "/Upload.aspx",
                    post_params: {
                        "ASPSESSID": "<%=Session.SessionID %>"},


post_params中設定的鍵值對將會以Form表單的形式傳遞到Upload.aspx,也就是SWFUpload提供了為請求增加自定義請求引數的介面。

 如果網站中還用到了Membership的FormsAuthentication驗證,則還需要把AUTHID也按照SessionID的方法進行處理

 swfu = new SWFUpload({
                    // Backend Settings
                    upload_url: "/Upload.ashx",
                    post_params: {
                        "ASPSESSID": "<%=Session.SessionID %>"},
                         "AUTHID" : "<%=Request.Cookies[FormsAuthentication.FormsCookieName].Value%>",


上面的程式碼把當前頁面的SessionId寫到ASPSESSID值中,當用戶上傳檔案後,ASPSESSID就會傳遞到伺服器上了,在Global.asax的Application_BeginRequest中新增如下程式碼:
protected void Application_BeginRequest(object sender, EventArgs e)
        {
            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)
            {
            }

            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)
            {
            }


        }
        void UpdateCookie(string cookie_name, string cookie_value)
        {
            HttpCookie cookie = HttpContext.Current.Request.Cookies.Get(cookie_name);
            if (cookie == null)
            {
                HttpCookie cookie1 = new HttpCookie(cookie_name, cookie_value);
                Response.Cookies.Add(cookie1);
            }
            else
            {
                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了。

如果網站是使用Windows方式驗證的,post_params:{

                           ASPSESSID: "<%=Session.SessionID %>",這樣便可,不需要在Application_BeginRequest寫任何方法。

相關閱讀