struts2 上传文件添加进度条

为了给用户更好体验,最进在struts2添加了上传进度条让用户知道上传过程时间,增加有好度。

由于以前做个 文件上传 没有用过 组件进行解析,直接用servlet 解析的,而现在 struts2 框架使用 commons-fileupload 解析上传文件.

通常我们在action  中声明 file,fileType,等字段  struts2 在执行action 方法时已经把 文件上传解析好了。进行封装后 传到 action, 通过所以无法在action 做文件解析监听.

struts2 上传原理form中设定的提交内容是二进制格式的,Dispatcher类的wrapRequest方法会将请求交由实现MultiPartRequest接口的JakartaMultiPartRequest

类来处理

在Struts2的JakartaMultiPartRequest类实现了MultiPartRequestWrapper接口, 里面的parse方法中才会真正来调用commons-fileupload组件的 ServletFileUpload类对请求进行解析,最后进行封装传入action.

知道原理后,思路也就清晰了。需要监听上传文件,则需要在这动文章.

首先需要在上传文件页面post提交文件, 在commons-fileupload 解析文件时,把解过程存入session, 然后在提交页面用ajax 请求另一个链接,读出session里面的 解析信息。显示在页面。

提交页面


   
1 < style type ="text/css" > 2 #progressBar { width : 400px ; height : 12px ; background : #FFFFFF ; border : 1px solid #000000 ; padding : 1px ; } 3 #progressBarItem { width : 30% ; height : 100% ; background : #FF0000 } 4 </ style > 5 < script type ="text/javascript" src ="js/jquery.js" ></ script > 6 < script type ="text/javascript" language ="javascript" > 7 var finished = true ; // 上传是否结束 8 function showStatus(){ 9 finished = false ; 10 $( ' #progressBarItem ' ).attr( ' width ' , ' 1% ' ); 11 setTimeout( ' callback() ' , 1000 ); 12 } 13 14 function callback(){ 15 if (finished) return ; 16 var url = ' paper/doFileProgress ' ; 17 var jv = ajaxGetReq(url); 18 alert(jv); 19 setTimeout( ' callback() ' , 1000 ); 20 } 21 </ script > 22 </ head > 23 < body > 24 < iframe name ="upload_iframe" width ="0" height ="0" ></ iframe > 25 < div id ="progressBar" >< div id ="progressBarItem" ></ div ></ div >< div id ="statusInfo" ></ div > 26 < form id ="form1" method ="post" action ="paper/addPaper" enctype ="multipart/form-data" target ="upload_iframe" onsubmit ="return showStatus()" > 27 < input type ="file" name ="file1" />< br /> 28 < input type ="file" name ="file2" />< br /> 29 </ form > 30 </ body >

target 属性默认是_self, 如果target 为默认值,则提交后的新页面会在当前窗口显示,造成当前窗口短暂地白屏。在页面添加一个隐藏iframe,把target属性指定为iframe,所以上传文件 当前页面看不来变化

UploadSatatus.java 显示状态类


   
1 public class UploadStatus { 2 3 private long bytesRead; // 已经上传的字节数,单位:字节 4 private long contentLength; // 所有文件的总长度,单位:字节 5 private int items; // 正在上传第几个文件 6 private long startTime = System.currentTimeMillis(); // 开始上传的时间,用于计算上传速度等 7 }

UploadListener.java 监听类


   
1 public class UploadListener implements ProgressListener{ 2 3 private UploadStatus status; 4 5 public UploadListener(UploadStatus status){ 6 this.status = status; 7 } 8 9 10 public void update(long bytesRead, long contentLength, int items) { 11 //上传组件会调用该方法 12 status.setBytesRead(bytesRead); //已读取的数据长度 13 status.setContentLength(contentLength); //文件总长度 14 status.setItems(items); //正在保存第几个文件 15 16 }

接下来 实现 struts2 2.3 版本 MultiPartRequest接口,  把

public class RefactorMultiPartRequest implements MultiPartRequest

复制一份JakartaMultiPartRequest类里面的类代码到 自己新建RefactorMultiPartRequest 类,同时修改parseRequest代码(继承JakartaMultiPartRequest也可以,由于这类里私有方法太多,不适合继承)


   
1 private List < FileItem > parseRequest(HttpServletRequest servletRequest, String saveDir) throws FileUploadException { 2 3 UploadStatus status = new UploadStatus(); // 上传状态 4 UploadListener listner = new UploadListener(status); // 监听器 5 servletRequest.getSession().setAttribute( " uploadStatus " , status); // 把状态放到session里去 6 7 8 DiskFileItemFactory fac = createDiskFileItemFactory(saveDir); 9 ServletFileUpload upload = new ServletFileUpload(fac); 10 upload.setSizeMax(maxSize); 11 upload.setProgressListener(listner); // 添加监听器 12 13 return upload.parseRequest(createRequestContext(servletRequest)); 14 }

在struts.xml里面加入覆盖JakartaMultiPartRequest类配置


   
1 < bean type ="org.apache.struts2.dispatcher.multipart.MultiPartRequest" name ="refactor" 2 class ="org.scirp.common.interceptor.RefactorMultiPartRequest" scope ="default" /> 3 4 < constant name ="struts.multipart.handler" value ="refactor" />

至于我怎么知道的,我也是阅读了人家文章 strut2 内部原理 , 不过我覆盖失败),调试还是调用原来的JakartaMultiPartRequest类,而不是调用我写的RefactorMultiPartRequest (现在还没解决,不知道是不是少写了配置,我解决方法是 在我项目里新建了一个包路径和JakartaMultiPartRequest一模一样的类,因为jdk 在相同包 java 文件时,会优先调用项目里的类)

然后新建一个读取进度方法


   
1 /** 2 * 显示文件上传的进度 3 */ 4 public void doFileProgress(){ 5 response.setHeader( " Cache-Control " , " no-store " ); // 禁止浏览器缓存 6 response.setHeader( " Pragrma " , " no-cache " ); // 禁止浏览器缓存 7 response.setDateHeader( " Expires " , 0 ); // 禁止浏览器缓存 8 9 UploadStatus status = (UploadStatus)session.getAttribute(ConfigKeys.UPLOAD_STATENAME); 10 if (status == null ){ 11 renderText( " error " ); 12 return ; 13 } 14 15 long startTime = status.getStartTime(); // 上传开始时间 16 long currentTime = System.currentTimeMillis(); // 现在时间 17 long time = (currentTime - startTime) / 1000 + 1 ; // 已传输的时间 单位:s 18 19 // 传输速度单位:byte/s 20 double velocity = (( double )status.getBytesRead()) / ( double )time; 21 // 估计总时间 22 double totalTime = status.getContentLength(); 23 // 估计剩余时间 24 double timeLeft = totalTime - time; 25 // 已经完成的百分比 26 int percent = ( int )( 100 * ( double )status.getBytesRead() / ( double )status.getContentLength()); 27 // 已经完成数单位:m 28 double length = (( double ) status.getBytesRead()) / 1024 / 1024 ; 29 // 总长度 单位:m 30 double totalLength = (( double ) status.getContentLength()) / 1024 / 1024 ; 31 32 // 我用的是json 33 JSONObject json = new JSONObject(); 34 json.put( " percent " , percent); 35 json.put( " length " , length); 36 json.put( " totalLength " , totalLength); 37 json.put( " velocity " , velocity); 38 json.put( " time " , time); 39 json.put( " totalTime " , totalTime); 40 json.put( " timeLeft " , timeLeft); 41 json.put( " fileNumber " , status.getItems()); 42 System.out.println(json.toString()); 43 renderText(json.toString()); 44 45 }

运行后

1

2

转载于:https://my.oschina.net/hlevel/blog/152646

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值