需求来源是这样的:上传一个很大的超过文件到服务器,服务器会解析这个excel,然后一条一条的插入到数据库,整个过程要耗费很长时间,因此当用户点击上传之后,需要显示一个进度条,并且能够根据后台的接收的数据量和处理的进度及时更新进度条。
分析:后台需要两个组件,uploadController.jsp用来接收并且处理数据,它会动态的把进度信息放到会话,另一个组件processController.jsp用来更新进度条;当用户点"上传"之后,形式被提交给uploadController.jsp,同时用射流研究…启动一个创建交互式、快速动态网页应用的网页开发技术请求到processController.jsp,ajax用获得的进度百分比更新进度条的显示进度,而且这个过程每秒重复一次;这就是本例的基本工作原理。
现在的问题是计算机网络服务器接收数据的时候怎么知道接收的数据占总数据的多少?如果我们从头自己写一个文件上传组件,那这个问题很好解决,关键是很多时候我们都是用的成熟的组件,比如apache commons文件上传比较幸运的是阿帕奇早就想到了这个问题,所以预留了接口可以用来获取接收数据的百分比;因此我就用阿帕奇公地文件上传来接收上传文件。
uploadController.jsp:
“% @”页面语言=“Java”导入=“Java”。乌提尔。*,java.io.*,org。阿帕奇。公地。文件上传。*,组织。阿帕奇。公地。文件上传。磁盘。disk fileitemfactory,org。阿帕奇。公地。文件上传。servlet。servlet。servlet文件上传'页面编码=' utf-8% %//注意上面的进口的冲突包是必须的//下面是使用阿帕奇公地文件上传接收上传文件;文件工厂工厂=new DiskFileItemFactory();servlet文件上传上传=新servlet文件上传(工厂);//因为内部类无法引用请求,所以要实现一个类我的进度监听器实现progress listener { private HttpServletrequest请求=NullMyProgreSlistener(HttpServletrequest请求){ this . request=request } public void update(long pBytesRead,long pContentLength,int pItems){ double percent=((double)pBytesRead/(double)pcontetlength);//上传的进度保存到会话,以便processController.jsp使用request.getSession().setAttribute(' uploadpercent ',百分比);} } upload.setProgressListener(新的MyProgressListener(请求));列表项=upload.parseRequest(请求);迭代器ITER=项目。迭代器();而(ITER。HasNeXt()){ file item item=(file item)ITER。NeXt();if(项目。isformfield()){ } else {//String字段名=item。getfield name();字符串FIlename=项目。GetName();//字符串内容类型=项。get content type();系统。出去。println();布尔IsInmemory=item。is INmemory();long SizeInBytes=item。getSize();文件上传文件=新文件(' c ://'系统。CurrentMemillis()。文件名。子字符串(文件名。LastIndexof('。'))));项目。写(上传的文件);}}out.write('{success:true,msg: '保存上传文件数据并分析超过成功!'}');出去。flush();%processController.jsp:
“% @”页面语言=“Java”导入=“Java”。乌提尔。*“ContentType=”文本/html;charset=UTF-8”页面编码=“utf-8”% %//注意上面的抬头是必须的。否则会有创建交互式、快速动态网页应用的网页开发技术乱码问题。//从会议取出上传百分比并送回浏览器对象百分比=request.getSession().getAttribute(' upload percent ');字符串msg=double d=0;如果(百分比==null){ d=0;}否则{d=(双倍)百分比;//系统。出去。println('过程控制器: ' d);}if(d1){//d1代表正在上传,msg='正在上传文件.';out . write(“{ success : true,msg: '' msg ' ',percentage:'' d ' ',finished : false }”);}else if(d=1){//d1代表上传已经结束,开始处理分析excel,//本例只是模拟处理excel,在会议中放置一个processExcelPercentage,代表分析超过的进度消息='正在分析处理超过.";字符串结束=' false double processExcelPercentage=0.0;对象o=request.getSession().getAttribute(' processExcelPercentage ');if(o==null){ processExcelPercentage=0.0;request.getSession().setAttribute(' processExcelPercentage ',0.0);}else{//模拟处理excel,百分比每次递增0.1 processExcelPercentage=(Double)o 0.1;request.getSession().setAttribute(' processExcelPercentage ',processExcelPercentage);if(processExcelPercentage=1){//当processExcelPercentage1代表超过分析完毕。request.getSession().removeAttribute('上传百分比');request.getSession().移除属性(' processeExcelPercentage//客户端判断是否结束的标志完成="真";} }退出。写入(“{ success : true,msg: '' msg ' ',percent : ' ' processExcelPercentage ' ',finished : ' finished ' }”);//注意返回的数据,成功代表状态//百分比是百分比//完成代表整个过程是否结束。}出去。flush();%表单页面上传。html:
html health eta http-equiv=' Content-Type ' Content=' text/html;字符集=utf-8 '/标题文件上传字段示例/titlelink rel='样式表type=' text/CSS ' href=' Ext/resources/CSS/Ext-all。CSS '/脚本类型=' text/JavaScript ' src=' http : Ext/adapter/Ext/Ext-base。js /脚本脚本类型=' text/JAVAScript ' src=' http : Ext/Ext-all。js '/脚本样式/head dya hreformpanel({ title : '上传超过文件,url:'uploadController.jsp?t=' new Date(),autoScroll:true,applyTo: 'form ',height: 120,width: 500,frame:false,fileUpload: true,defaultType:'textfield ',labelWidth:200,items:[{xtype:'field ',fieldLabel: '请选择要上传的超过文件,allowBlank:false,inputType:'file ',name:'file'}],button :[{ text : '开始上传,手柄:函数(){//点击'开始上传'之后,将由这个功能来处理if(fm.form.isValid()){//验证形式,本例略掉了//显示进度条延伸文件系统MessageBox.show({ title: '正在上传文件,//msg: '处理.width:240,progress:true,closable:false,按钮3360 { Cancel : ' Cancel ' });//表单提交fm.getForm().submit();//设置一个定时器,每500毫秒向过程控制器发送一次创建交互式、快速动态网页应用的网页开发技术请求var I=0;var timer=setInterval(function(){//请求事例延伸文件系统Ajax.request({ //下面的全球资源定位器(统一资源定位符)的写法很关键,我为了这个调试了好半天//以后凡是在创建交互式、快速动态网页应用的网页开发技术的请求的全球资源定位器(统一资源定位符)上面都要带上日期戳, //否则极有可能每次出现的数据都是一样的, //这和浏览器缓存有关url: 'processController.jsp?t=' new Date(),method: 'get ',//处理创建交互式、快速动态网页应用的网页开发技术的返回数据成功:函数(响应,选项){状态=响应。回应ext ' ' I;var obj=Ext。乌提尔。JSON。解码(响应。响应ext);如果成功!=false){ if(obj。已完成){ clearInterval(计时器);//状态=响应。响应文本;延伸文件系统MessageBox.updateProgress(1,"已完成"、"已完成");延伸文件系统消息框。hide();}else{Ext .消息框。updateprogress(obj。百分比。味精);}}},失败:函数(){ clearInterval(计时器);延伸文件系统Msg.alert('错误', '发生错误了。');} });}, 500);} else{ Ext .Msg.alert('消息','请先选择超过文件再上传。');}} }]});/script/html把这三个文件放到tomcat/webapps/ROOT/,同时把外面的(外部的简写)的主要文件也放到这里,启动雄猫即可测试:http://localhost :8080/上传。超文本标记语言
我的资源里面有完整的示例文件:点击下载,下载活力文件之后解压到tomcat/webapps/ROOT/即可测试。
最后需要特别提醒,因为用到了街头流氓的文件上传组件,因此,需要把common-fileupload.jar放到根/网络-信息/库下。