文档章节

struts2 上传文件添加进度条

hlevel
 hlevel
发布于 2013/08/14 16:31
字数 1263
阅读 7596
收藏 29

为了给用户更好体验,最进在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

© 著作权归作者所有

hlevel

hlevel

粉丝 42
博文 9
码字总数 8504
作品 0
武汉
程序员
私信 提问
加载中

评论(6)

hlevel
hlevel 博主

引用来自“yibuyimeng”的评论

var jv = ajaxGetReq(url); 这个ajaxGetUrl是ajax? 这个url是servlet?
是的,才看到不好意思.
y
yibuyimeng
var jv = ajaxGetReq(url); 这个ajaxGetUrl是ajax? 这个url是servlet?
dunhanson
dunhanson
struts2配置文件应该这么配置
  <constant name="struts.multipart.parser" value="com.us.servlet.MyMultiPartRequest" />
  <constant name="struts.multipart.handler" value="com.us.servlet.MyMultiPartRequest" />
落泪归枫
落泪归枫

引用来自“hlevel”的评论

引用来自“lmh”的评论

那控制文件大小是怎么处理的?

不是有一个总长度的属性吗?totalLength 用那就可以判断出文件大小 然后和你限制大小做比较

那是不是上传的文件得传到服务器上后才能知道大小
hlevel
hlevel 博主

引用来自“lmh”的评论

那控制文件大小是怎么处理的?

不是有一个总长度的属性吗?totalLength 用那就可以判断出文件大小 然后和你限制大小做比较
落泪归枫
落泪归枫
那控制文件大小是怎么处理的?
struts2框架实现上传文件进度条功能

在实现上传进度条功能中,主要是的思想是利用struts2中定义的ProgressListener(进度监听器),里面有一个update(long readedBytes,long totalBytes,int currentItem) 方法,当文件用二进制文...

cumtm3
2016/05/23
60
0
status2.3.4和struts2.3.15.1 Fileupload上传文件简单分析

struts2漏洞爆发,近日修补漏洞,struts2.3.4.1升级到struts2.3.15.1,发现以前用uploadFile能正常上传文件显示进度条现在不能正常工作了,List items = upload.parseRequest(request),items...

guhai2004
2013/08/29
4.2K
1
Fastupload 0.4.7 发布,支持 struts2

Fastupload 0.4.7这个版本中主要增加了支持struts2的文件上传功能的“插件”,修复了解析IE7,IE8下某些版本上传的请求数据中文件名问题(这里感谢lkclkc 网友报的bug及提供的解决思路)。 ...

仪山湖
2012/10/28
1K
1
基于HT for Web矢量实现HTML5文件上传进度条

在HTML中,在文件上传的过程中,很多情况都是没有任何的提示,这在体验上很不好,用户都不知道到时有没有在上传、上传成功了没有,所以今天给大家介绍的内容是通过HT for Web矢量来实现HTML5...

xhload3d
2015/06/08
209
0
HTML5矢量实现文件上传进度条

在HTML中,在文件上传的过程中,很多情况都是没有任何的提示,这在体验上很不好,用户都不知道到时有没有在上传、上传成功了没有,所以今天给大家介绍的内容是通过HT for Web矢量来实现HTML5...

xhload3d
2015/11/22
289
1

没有更多内容

加载失败,请刷新页面

加载更多

SpringBoot 集成MongoDB

一、MongoDB 简介 MongoDB 如今是最流行的 NoSQL 数据库,被广泛应用于各行各业中,很多创业公司数据库选型就直接使用了 MongoDB,但对于大部分公司,使用 MongoDB 的场景是做大规模数据查询...

zw965
25分钟前
11
0
使用 Envoy 和 AdGuard Home 阻挡烦人的广告

> 原文链接:使用 Envoy 和 AdGuard Home 阻挡烦人的广告 通常我们使用网络时,宽带运营商会为我们分配一个 DNS 服务器。这个 DNS 通常是最快的,距离最近的服务器,但会有很多问题,比如: ...

米开朗基杨
58分钟前
19
0
springboot之全局处理异常封装

springboot之全局处理异常封装 简介 在项目中经常出现系统异常的情况,比如NullPointerException等等。如果默认未处理的情况下,springboot会响应默认的错误提示,这样对用户体验不是友好,系...

Purgeyao
今天
24
0
cookie

cookie: n. 饼干;小甜点 为什么会引入Cookie(在客户端保持http状态) 因为http协议是一种无状态协议,web服务器本身不能识别出哪些请求是同一个服务器发送的,浏览器的每一次请求都是独立...

五公里
今天
25
0
PHP常用函数

<?php/** * 获取客户端IP * @return [string] [description] */function getClientIp() { $ip = NULL; if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) { $arr = explode('......

半缘修道半缘君丶
今天
15
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部