Uploadify ashx文件中Context.Session为空。

5

我的网站中有一个文件上传功能,使用uploadify进行上传,它使用ashx页面将文件上传到数据库。在IE中运行良好,但在Mozilla中context.Session为null。我还使用了IReadOnlySessionState来读取会话。

如何像IE一样在Mozilla中获取会话。

这是我编写的ashx代码:

public class Upload : IHttpHandler, IReadOnlySessionState 
{    
    HttpContext context;
    public void ProcessRequest(HttpContext context)
    {
        string UserID = context.Request["UserID"];

        context.Response.ContentType = "text/plain";
        context.Response.Expires = -1;
        XmlDocument xDoc = new XmlDocument();
        HttpPostedFile postedFile = context.Request.Files["Filedata"];
        try
        {
            if (context.Session["User"] == null || context.Session["User"].ToString() == "")
            {
                context.Response.Write("SessionExpired");
                context.Response.StatusCode = 200;
            }
            else
            {
                  // does the uploading to database
            }
        }
   }
}

在IE浏览器中,Context.Session["User"]总是有值,但在Mozilla浏览器中始终为null。


可能是一个愚蠢的问题,但你在Mozilla中启用了cookie吗? - Darin Dimitrov
@deepu,你能展示一下你代码的相关部分吗(客户端和服务器)? - Darin Dimitrov
我已经添加了在ashx页面完成的代码示例,我在IE中很好地获取了context.session。但是当我来检查Mozilla时,它总是得到null并且上传文件时会话过期。在搜索时,我发现在IHttpHandler中对于Mozilla很难获取会话。是否有任何方法可以获取会话? - deepu
谢谢你的回答,但是在使用这段代码后,我遇到了很多与服务器相关的问题,所以并没有得到帮助。我只是通过对之前代码的简单修改找到了一个解决方案。我创建了一个函数来检查会话是否已过期,并将其作为参数传递给uploadify的script-data,在ashx文件中,我检查该参数以查看会话是否存在。如果返回会话已过期,则不会进行上传。这对我有用。在使用过程中没有发现任何问题。希望这能解决我的问题。 - deepu
5个回答

11

你需要将sessionId添加到uploadify的post参数中,并在global.asax文件的OnBeginRequest事件中还原ASP.NET_SessionId cookie。这实际上是flash和cookies之间的bug

我已经创建了用于会话和身份验证cookie恢复的模块,以使flash和asp.net会话正常工作,所以我认为它对你很有用:

public class SwfUploadSupportModule : IHttpModule
{
    public void Dispose()
    {
        // clean-up code here.
    }

    public void Init(HttpApplication application)
    {
        application.BeginRequest += new EventHandler(OnBeginRequest);
    }

    private void OnBeginRequest(object sender, EventArgs e)
    {
        var httpApplication = (HttpApplication)sender;

        /* we guess at this point session is not already retrieved by application so we recreate cookie with the session id... */
        try
        {
            string session_param_name = "ASPSESSID";
            string session_cookie_name = "ASP.NET_SessionId";
            if (httpApplication.Request.Form[session_param_name] != null)
            {
                UpdateCookie(httpApplication, session_cookie_name, httpApplication.Request.Form[session_param_name]);
            }
            else if (httpApplication.Request.QueryString[session_param_name] != null)
            {
                UpdateCookie(httpApplication, session_cookie_name, httpApplication.Request.QueryString[session_param_name]);
            }
        }
        catch
        {
        }

        try
        {
            string auth_param_name = "AUTHID";
            string auth_cookie_name = FormsAuthentication.FormsCookieName;

            if (httpApplication.Request.Form[auth_param_name] != null)
            {
                UpdateCookie(httpApplication, auth_cookie_name, httpApplication.Request.Form[auth_param_name]);
            }
            else if (httpApplication.Request.QueryString[auth_param_name] != null)
            {
                UpdateCookie(httpApplication, auth_cookie_name, httpApplication.Request.QueryString[auth_param_name]);
            }
        }
        catch
        {
        }            
    }

    private void UpdateCookie(HttpApplication application, string cookie_name, string cookie_value)
    {
        var httpApplication = (HttpApplication)application;

        HttpCookie cookie = httpApplication.Request.Cookies.Get(cookie_name);
        if (null == cookie)
        {
            cookie = new HttpCookie(cookie_name);
        }
        cookie.Value = cookie_value;
        httpApplication.Request.Cookies.Set(cookie);
    }
}

同时你需要在web.config文件中注册上述模块:

<system.webServer>
  <modules runAllManagedModulesForAllRequests="true">
    <add name="SwfUploadSupportModule" type="namespace.SwfUploadSupportModule, application name" />
  </modules>
</system.webServer>

你能否详细解释一下这个方法? - deepu
这是一个httpModule,它在每个开始请求时检查是否存在'ASPSESSID'参数,如果找到参数,则重新创建cookie。就这些了。 - Andrew Orsich
太棒了的提示!谢谢batishchev - Alex KeySmith
各位,如果你们编译这个答案和https://dev59.com/enI-5IYBdhLWcg3wsKh4,你将得到一个真正可行的解决方案。 - sir_neanderthal
我遇到了一个奇怪的问题,我尝试了以上所有选项,但仍然无法在服务器上更新cookie,但在我的开发机器上却可以正常工作。有人遇到过这种问题吗? - FosterZ

1

Context.Session 为空.. 因为连接到 HttpHandler 的另一个 Context.Session
(调试并尝试:在文件输入所在的位置中使用Context.Session.SessionId与在Upload.ashx中使用的Context.Session.SessionId不同)!

我建议一个解决方法:通过引用传递第二个会话中需要的元素(在我的示例中,我使用sessionId变量传递原始的SessionId

....
var sessionId = "<%=Context.Session.SessionID%>";
var theString = "other param,if needed";
$(document).ready(function () {
    $('#fileInput').uploadify({
        'uploader': '<%=ResolveUrl("~/uploadify/uploadify.swf")%>',
        'script': '<%=ResolveUrl("~/Upload.ashx")%>',
        'scriptData': { 'sessionId': sessionId, 'foo': theString },
        'cancelImg': '<%=ResolveUrl("~/uploadify/cancel.png")%>',
 ....

并在 .ashx 文件中使用这些项。

public void ProcessRequest(HttpContext context)
{
    try
    {
       HttpPostedFile file = context.Request.Files["Filedata"];
       string sessionId = context.Request["sessionId"].ToString();
      ....

如果您需要共享复杂元素,请使用Context.Application而不是Context.Session,使用原始SessionID:Context.Application["SharedElement"+SessionID]


0

很可能是服务器未能设置或客户端未能发送回来的某些内容出了问题。

退回到较低级别 - 使用网络诊断工具,如FiddlerWireshark来检查发送到/从您的服务器的流量,并比较IE和Firefox之间的差异。

查看标头以确保cookie和表单值按预期发送回服务器。


0
我创建了一个函数来检查会话是否已过期,然后将其作为参数传递到uploadify的script-data中,在ashx文件中检查该参数以查看会话是否存在。如果返回会话已过期,则不会进行上传。这对我很有效,没有发现任何问题。希望这能解决我的问题。

0

我曾经遇到过一个与 .ashx 文件相关的类似问题。解决方法是处理程序必须实现 IReadOnlySessionState(只读访问)或 IRequiresSessionState(读写访问)。例如:

public class SwfUploadSupportModule : IHttpHandler, IRequiresSessionState { ... }

这些接口不需要任何额外的代码,但作为框架的标记。

希望这可以帮到你。

乔纳森


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接