ASP.NET关于Session_End触发与否的问题
项目背景:
要求开发一个篆文识别网站,由于之前做好了WinForm的,把系统直接移植到WebForm上就好。工作比较简单,但确实遇到不少问题。
核心问题是:
篆文识别涉及到用户对原始图片的预处理(例如二值化、去除纹理等等),Win应用可以直接new Bitmap把过渡图都放在内存里,再用PictureBox控件显示出来即可。而Web应用里的图像显示控件是Image,只能通过设置ImageUrl来改变正在显示的图片。也就是说,要想显示图片,必须先把它存储为物理文件。
关键问题:
1.怎么获取原图,就是怎么把Image显示的图像转化为我们可以操作的Bitmap对象?
2.怎么把处理结果保存为物理文件(*.png)?
3.怎么把用户留下的临时文件清空?(前面两个都好办,这个才是关键)
解决方案:
1.两行代码轻松搞定
//获取当前图片
string path = Server.MapPath(imgShow.ImageUrl);
Bitmap img = new Bitmap(path);
2.同上
//保存临时文件
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()处理,它可能是这样子的:
//删除本次会话产生的临时文件 //文件路径
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里面取出来,循环删除就好
就像这样:
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,如果里面没有下面的内容,就把下面的代码添进去
<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触发与否的问题的更多相关文章
- ASP.NET页面回车键触发Button按钮事件问题
首先了解一下Button.UseSubmitBehavior属性. 获取或设置一个布尔值,该值指示 Button 控件使用客户端浏览器的提交机制还是 ASP.NET 回发机制. 如果该控件使用了客户端 ...
- 深入理解asp.net SessionState
web Form 网页是基于HTTP的,它们没有状态, 这意味着它们不知道所有的请求是否来自同一台客户端计算机,网页是受到了破坏,以及是否得到了刷新,这样就可能造成信息的丢失. 于是, 状态管理就成了 ...
- Asp.Net复习篇之Asp.Net生命周期与Asp.Net页的生命周期
Asp.Net生命周期与Asp.Net页的生命周期是一个比较重要的话题,有时可能似乎知道一些,但又说不出个所以然,而且时常把这两个概念混淆.现在也是该好好理清思路,把这两个概念搞懂. Asp.Net生 ...
- [译] ASP.NET 生命周期 – ASP.NET 请求生命周期(二)
ASP.NET 请求生命周期 全局应用类也可以用来跟踪每个独立请求的生命周期,包括请求从 ASP.NET 平台传递到 MVC 框架.ASP.NET 框架会创建一个定义在 Global.asax 文件中 ...
- ASP.NET 生命周期(原文翻译)
在网上看到这篇文章,老外写的,里面很多图片挺精致,顺带翻译过来给大家分享下,英语太次好多地方都翻不过来 ASP.NET application and page life cycle Download ...
- ASP.NET给Table动态添加删除行,并且得到控件的值
ASP.NET给Table动态添加控件并且得到控件的值 由于跟老师做一个小的项目,可是我自己又不太懂js,所以一直为动态建立表格并且能动态的取值和赋值感到苦恼.起初在网上找到了一些js资源,解决了动态 ...
- 服务器调用JS
服务器控件调用JS一.两类JS的触发设计1.提交之前的JS -- 加js的事件例:<script language="javascript"> // 构造函数 func ...
- Repeater实例应用
在实际开发过程中,涉及到数据绑定,分页,以及一对多展示数据时,遇到这样的需求我们怎么解决呢?下面以帖子展示来逐一说明. 帖子主要由两部分组成,第一部分是发帖人的原创内容部分,第二部分是用户评论部分,这 ...
- 点击datalist中Button按钮出现“回发或回调参数无效......”
遇到问题: 回发或回调参数无效.在配置中使用 <pages enableEventValidation="true"/> 或在页面中使用 <%@ Page ...
随机推荐
- BeanFactory 和 ApplicationContext的区别
今天在网上查资料无意中看到这一行代码 BeanFactory factory = new ClassPathXmlApplicationContext("applicationContext ...
- centos 网卡聚合及Cisco交换机链路聚合
一.配置环境 centos 系统.网卡1口和2口做链路聚合. 交换机网口 6口和7口. 二.服务器操作步骤 centos 6 1.创建一个channel bonding interface #v ...
- 【校招面试 之 C/C++】第19题 C++ STL(一)
容器名称 说明 vector 典型的序列容器,C++标准严格要求次容器的实现内存必须是连续的,唯一可以和标准C兼容的stl容器,任意元素的读取.修改具有常数时间复杂度,在序列尾部进行插入.删除是常 ...
- 【校招面试 之 C/C++】第15题 C 回调函数
转自:https://segmentfault.com/a/1190000008293902 做略微改动 什么是回调函数 我们先来看看百度百科是如何定义回调函数的: 回调函数就是一个通过函数指针调用的 ...
- pyhon之函数参数
#函数的参数分为形参和实参,其中形参就是形式参数,是在创建函数的时候定义,实参就是实际参数,是在调用的函数的时候创建,这个并不是重点,具体#的参数内部,我们可以把参数分为以下4种# 1.普通参数# 2 ...
- .NET格式化字符串详细说明
DataFormatString属性:{0:Bxx}B为取值类型 C 以货币格式显示数值. D 以十进制格式显示数值. E 以科学记数法(指数)格式显示数值. F 以固定格式显示数值. G 以常规格式 ...
- dbus通信与接口介绍
DBUS是一种高级的进程间通信机制.DBUS支持进程间一对一和多对多的对等通信,在多对多的通讯时,需要后台进程的角色去分转消息,当一个进程发消息给另外一个进程时,先发消息到后台进程,再通过后台进程将信 ...
- dump打印
- Ubuntu 配置网卡信息
关于图形界面的配置,我这里就不多介绍了,这个很简单.这里介绍的是如何通过修改配置文件来实现虚拟网卡. 首先介绍ubuntu(我这里使用的是ubuntu-16.04)下虚拟网卡的配置 1.先用ifcon ...
- 属性表格 datagridproperty
http://www.cnblogs.com/yxlblogs/p/3468921.html