ASP.NET关于Session_End触发与否的问题

项目背景:

要求开发一个篆文识别网站,由于之前做好了WinForm的,把系统直接移植到WebForm上就好。工作比较简单,但确实遇到不少问题。

核心问题是:

篆文识别涉及到用户对原始图片的预处理(例如二值化、去除纹理等等),Win应用可以直接new
Bitmap把过渡图都放在内存里,再用PictureBox控件显示出来即可。而Web应用里的图像显示控件是Image,只能通过设置ImageUrl来改变正在显示的图片。也就是说,要想显示图片,必须先把它存储为物理文件。

关键问题:

1.怎么获取原图,就是怎么把Image显示的图像转化为我们可以操作的Bitmap对象?

2.怎么把处理结果保存为物理文件(*.png)?

3.怎么把用户留下的临时文件清空?(前面两个都好办,这个才是关键)

解决方案:

1.两行代码轻松搞定

?





1

2

3

//获取当前图片

string
path = Server.MapPath(imgShow.ImageUrl);

Bitmap img = new
Bitmap(path);

2.同上

?





1

2

3

4

5

6

7

//保存临时文件

string
newPath = Server.MapPath("temp/tmp.png");

img.Save(newPath);

//设置ImageUrl

imgShow.ImageUrl = "~/temp/tmp.png";

//释放资源

img.Dispose();

3.最简单的思路就是:

<1>用SessionID来作为临时文件名(区分不同用户),建立用户与临时文件的联系

<2>当用户注销时,把该用户留下的所有临时文件删掉(删除所有文件名含当前sid的文件)

详细步骤:

<1>没什么好说的,文件名 = Session.SessionID + "_abc.png" 即可

<2>问题来了,如何catch用户注销这个动作,并在这之前执行我们的代码来清理临时文件

我们找到了Global.aspx里的Session_End方法,这个理论上能够满足我们的需求(注意Session_End与Session_OnEnd的区别,这里不再详述)

我们要做的就是在Session_End方法体里面添上clearTmpFiles()处理,它可能是这样子的:

?





1

2

3

4

5

6

7

8

9

10

11

12

13

14

//删除本次会话产生的临时文件

//文件路径

List<string> paths = new
List<string>();

paths.Add(Server.MapPath("temp/"
+ Session.SessionID + "_b.png"));//二值化文件

paths.Add(Server.MapPath("temp/"
+ Session.SessionID + "_d.png"));//纹理消除文件

paths.Add(Server.MapPath("temp/"
+ Session.SessionID + "_search.png"));//搜索结果文件

paths.Add(Server.MapPath("temp/"
+ Session.SessionID + "_p1.png"));//图像分割文件1

paths.Add(Server.MapPath("temp/"
+ Session.SessionID + "_p2.png"));//图像分割文件2

paths.Add(Server.MapPath("temp/"
+ Session.SessionID + "_p3.png"));//图像分割文件3

paths.Add(Server.MapPath("temp/"
+ Session.SessionID + "_p4.png"));//图像分割文件4

//删除

foreach(string
path in
pathes)

        File.Delete(path);

现在我们把上面的处理添进Session_End里面了,测试一下...

发现我们失败了,临时文件还在...为什么呢,可能是因为Session_End方法没有执行(该事件没有被触发)

于是疯狂地百度、Google,无果。很多人都遇到了这个问题,但好像所有人都没有解决,其中stackoverflow上面的说法就比较玄乎了,看似靠谱,经实测根本没这回事儿,链接是这个:http://stackoverflow.com/questions/4813462

。。。

不甘心的想了很久,最终找到了原因:

不是因为Session_End没有被触发,而是里面的代码有错误,Session的运行机制决定了这里面的错误不会被开发者发现(对运行时的错误不会有任何提示,也别想用什么Response.Write来尝试调试,因为根本不会有任何反应...导致的结果就是:所有人都以为Session_End没有被触发...)

Web应用的生命周期是这样的:Application_Start -> Session_Start
-> Session_End -> Application_End

这就是事件被触发的顺序,A事件occur -> 执行对应方法

Session_End方法执行时遵循的原则是【一旦遇到错误,立即返回】,这就是为什么所有人都以为它没有被触发的原因(完全感受不到嘛T_T)

那么什么情况算是错误?

在Session_End里面调用Server.MapPath()就算错误,没有为什么,这是龟腚,要用它,就必须遵守它

搞清楚问题是什么就好办了,对症下药:

a.当用户连接时(Session_Start)把临时文件路径paths存在Session对象里面

b.当用户注销时候(Session_End)把paths从Session里面取出来,循环删除就好

就像这样:

?





1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

void Session_Start(object
sender, EventArgs e)

{

    // 在新会话启动时运行的代码

    //存储path

    //文件路径

    List<string> paths = new
List<string>();

    paths.Add(Server.MapPath("temp/"
+ Session.SessionID + "_b.png"));//二值化文件

    paths.Add(Server.MapPath("temp/"
+ Session.SessionID + "_d.png"));//纹理消除文件

    paths.Add(Server.MapPath("temp/"
+ Session.SessionID + "_search.png"));//搜索结果文件

    paths.Add(Server.MapPath("temp/"
+ Session.SessionID + "_p1.png"));//图像分割文件1

    paths.Add(Server.MapPath("temp/"
+ Session.SessionID + "_p2.png"));//图像分割文件2

    paths.Add(Server.MapPath("temp/"
+ Session.SessionID + "_p3.png"));//图像分割文件3

    paths.Add(Server.MapPath("temp/"
+ Session.SessionID + "_p4.png"));//图像分割文件4

    Session.Add("paths", paths);

}

void
Session_End(object
sender, EventArgs e)

{

    // 在会话结束时运行的代码。

    // 注意: 只有在 Web.config 文件中的 sessionstate 模式设置为

    // InProc 时,才会引发 Session_End 事件。如果会话模式设置为 StateServer

    // 或 SQLServer,则不会引发该事件。

    

    //删除本次会话产生的临时文件

    //文件路径

    List<string> pathes = (List<string>)Session["paths"];

    //删除

    foreach(string
path in
pathes)

        File.Delete(path);

}

测试代码:

Session.Abandon();//注销Session

//放在Button的Click里面,点一点立竿见影

经过测试没有问题

总结:

如果你的Session_End“没有被触发”,请往下看:

1.检查配置文件Web.config,如果里面没有下面的内容,就把下面的代码添进去

?





1

2

<sessionState mode="InProc"
timeout="1"></sessionState>

//说明:<sessionState>是<system.web>的子元素,其中timeout属性表示Session的过期时间,单位是分钟,上面的意思是用户一分钟在页面无任何操作则Session失效

2.检查你的方法体里面有没有出现Server的相关调用(如Server.MapPath("xxx");),如果有,请看上面的解决方法

3.你的操作是不是只能写在Session_End里面?善后操作能不能通过用户注销或者关闭浏览器时弹出确认框点击确定来触发?如果Session_End还是不能正常工作,不妨试试这种方式

P.S.为什么不用上面提到的确认框的方式来解决这个问题?

因为浏览器兼容问题,主流的浏览器有IE、FF、GC...很难对所有浏览器考虑全面,本机用的是GC,很多JS代码都不能达到预期效果

另外,用确认框来善后需要考虑:浏览器兼容性问题、异常退出问题(用任务管理器暴力关掉、Alt + F4、任务栏右键关闭...)

用Session_End善后的优点是:无论用户是正常注销还是异常退出,其sid失效的时候都会触发Session_End,因为Session是保存在Server的,不会出现意外

ASP.NET关于Session_End触发与否的问题,布布扣,bubuko.com

时间: 2024-12-10 18:53:18

ASP.NET关于Session_End触发与否的问题的相关文章

深入理解asp.net SessionState

web Form 网页是基于HTTP的,它们没有状态, 这意味着它们不知道所有的请求是否来自同一台客户端计算机,网页是受到了破坏,以及是否得到了刷新,这样就可能造成信息的丢失. 于是, 状态管理就成了开发网络应用程序的一个实实在在的问题.    在ASP中能够通过Cookie .查询字符串. 应用程序.会话(Session) 等轻易解决这些问题.现在在ASP.NET环境中,我们依然可以使用这些功能,并且功能更加强大.状态管理分为服务端和客户端两种情况, 这里只是介绍 服务端状态管理: 与Appl

服务器控件在客户端触发alert对话框后,根据情况进行回发服务器操作

通常,ASP.NET服务器控件出触发后,即使使用js引发了alert对话框,确认alert对话框后,也会造成回发 这篇讲诉如何点击服务器按钮控件,触发客户端alert后,在符合条件的情况下,才将信息回发.这篇采用的是form认证方式验证用户身份,有关form认证的案例过程,我将单独开辟博客讲解. 步骤一.服务器后台Page_Load事件 public int isLoginUser; protected void Page_Load(object sender, EventArgs e) { i

ASP.NET 生命周期(原文翻译)

在网上看到这篇文章,老外写的,里面很多图片挺精致,顺带翻译过来给大家分享下,英语太次好多地方都翻不过来 ASP.NET application and page life cycle Download source code - 4.03 KB 目录 简介 两步处理法 创建ASP.NET环境 使用MHPM事件处理请求 在哪些事件里我们哪些事? 一个简单的示范代码 放大ASP.NET页面事件 关于源码 references 简介 在这篇文章,我们将努力弄明白从用户发送请求开始到浏览器渲染完毕过程中

暑假闲着没事第一弹:基于Django的长江大学教务处成绩查询系统

本篇文章涉及到的知识点有:Python爬虫,MySQL数据库,html/css/js基础,selenium和phantomjs基础,MVC设计模式,django框架(Python的web开发框架),apache服务器,linux(centos 7为例)基本操作.因此适合有以上基础的同学学习. 声明:本博文只是为了纯粹的技术交流,敏感信息本文会有所过滤,大家见谅(由于任何缘故导致长江大学教务处网站出现问题,都与本人无关). 实现思路:在没有教务处数据接口的前提下(学生的信息安全),那也只有自己写爬

前台调用后台事件和方法实现小结

在实际开发过程中,我们的HTML元素需要调用后台,而且需要让后台进行复杂运算后再进行数据重新绑定操作,遇到这样的问题怎么办呢?可能有人说在后台创建一个方法,该方法实现绑定数据操作,但是实际呢?结果不尽人意,它没有执行绑定的实现,而只是简单的执行一下方法但是前台无反应,为什么出现这样的情况?原来前台调用后台方法其实只是返回结果,对实现过程及元素组合变化不管不问,它只是关注执行后的结果,不为过程买单,那么有什么方法解决这个问题呢?想想?我们可不可以让前台HTML元素触发ASP.NET按钮来触发事件呢

服务器调用JS

服务器控件调用JS一.两类JS的触发设计1.提交之前的JS -- 加js的事件例:<script language="javascript"> // 构造函数 function test() { alert("abcdefg"); return true; } </script> // 添加点击事件,点击按钮后调用test 返回值,如果获得Faluse 则不执行C#代码 :true 执行代码: <asp:Button ID="

大家好

http://www.yugaopian.com/people/259723 http://www.yugaopian.com/people/259744 http://www.yugaopian.com/people/259783 http://www.yugaopian.com/people/259824 http://www.yugaopian.com/people/259839 http://www.yugaopian.com/people/259933 http://www.yugao

阿哥吗卡怪每次哦阿哥看啦过啦嘎开吃麻辣个啊蓝光

http://www.xx186.com/web/web_kpic.asp?id=156613http://www.xx186.com/web/web_kpic.asp?id=156608http://www.xx186.com/web/web_kpic.asp?id=156605http://www.xx186.com/web/web_kpic.asp?id=156602http://www.xx186.com/web/web_kpic.asp?id=156600http://www.xx18

风格更家霍建华

http://www.9ku.com/fuyin/daogaoo.asp?dgid=119864http://www.9ku.com/fuyin/daogaoo.asp?dgid=119867http://www.9ku.com/fuyin/daogaoo.asp?dgid=119876http://www.9ku.com/fuyin/daogaoo.asp?dgid=119879http://www.9ku.com/fuyin/daogaoo.asp?dgid=119883http://www