【转】小议swfupload的bug及解决之道
前 段时间公司出了个变态需求,要求上传文件时支持多文件上传,实时显示上传进度,上网搜索一番,决定使用swfupload这个基于flash的上传组件. 花了几天时间搞定,页面效果也相当令人满意.但是swfupload选中多个文件后,它的上传处理方式是每上传完一个文件就结束action,意即一个 action无法接收多个文件,于是问题来了,我想在所有文件上传完成后再执行一些操作,该怎么办呢,最简单的方法莫过于每上传完一个文件,就把它放到 session里,最后所有文件都上传完成后从session里取得这些文件进行处理.
问题是解决了,接下来有一次我打开Firefox进 行上传操作,却发现了奇怪的问题,上传完成后取不到这些文件了.费了一番周折,我试着在后台打出sessionId看看,却发现上传完成转入另一个 action后sessionId离奇般的换了一个!众所周知,session实现原理有两个,cookie和url重写,难道是swfupload上传 的时候丢失了sessionid?( 关于session的原理请参见我的另一篇文章Session原理 , 这里就不再详述.),于是我打开HttpLook工具(关于该工具的使用请自行baidu之或google之.)对操作进行监听,发现FireFox在上 传时并没有把Cookie中的JSESSIONID放到HEADER中返回服务器,然而IE下却是正常的.于是我上网搜索了一下,终于找到了原因:
这 是swfupload的一个bug(严格的说是Flash Player的bug,所有基于flash的上传组件都存在这个问题,只能等待Flash官方进行修复),在使用swfupload的时候,非IE浏览器 只会把持久化的cookie传回服务器,而session却是保存在内存中的cookie,swfupload不会把内存中的cookie传给服务器,这 是flash的一个bug,我们只能绕过它.我又找了一下,发现swfupload官方有关于这方面的讨论,也讲了绕过的方法,不过都是ASP或PHP的 代码,没有JAVA的,网上找了很久也没有,看样子我只能自己想办法解决了.
一开始我想能不能传个sessionId给服务器,然后让服务 器获得这个session呢?但是马上我就放弃了,servlet-api并没有提供访问其他session的方法.于是我想,session实现原理有 两个,cookie和url重写,cookie貌似不行了,那url重写呢?url重写也就是在action后面加 上";jsessionid=*************************"这样的方式,于是我修改了一下swfupload的初始化配置,原来 是这样的(截取一部分):
var settings = {
flash_url : "<%=request.getContextPath()%>"+"/script/swfupload/swfupload.swf",
upload_url: "upload.action" //处理文件上传的action
}
修改后如下:
var settings = {
flash_url : "<%=request.getContextPath()%>"+"/script/swfupload/swfupload.swf",
upload_url: "upload.action;jsessionid=<%=ActionContext.getSession().getId()%>" //处理文件上传的action
}
修改好后在Firefox下重试了一下,竟然成功了,很好.
经过这次的编程,我对session的实现原理认识更深刻了.