给文件上传添加进度条,整了两天终于成功了。
想要添加一个上传的进度条,通过分析,应该是需要不断的去访问服务器,询问上传文件的大小。通过已上传文件的大小,
和上传文件的总长度来评估上传的进度。
实现监听器ProgressListener接口,可以实时获取上传文件的长度。
public class FileUploadListener implements ProgressListener{ private HttpSession session; public FileUploadListener(HttpServletRequest request) { session = request.getSession(); FileState state = new FileState(); // 自定义FileState POJO类,储存状态信息 session.setAttribute("state", state); } @Override public void update(long readedBytes, long totalBytes, int currentItem) { // TODO Auto-generated method stub //System.out.println("update:"+readedBytes+";"+totalBytes+";"+currentItem); FileState state = (FileState) session.getAttribute("state"); state.setReadedBytes(readedBytes); // 已读数据的长度 state.setTotalBytes(totalBytes); // 文件总长度 state.setCurrentItem(currentItem); // 正在保存第几个文件 } }
FileState类
public class FileState { private long readedBytes = 0L; // 已经上传的字节数,单位:字节 private long totalBytes = 0L; // 所有文件的总长度,单位:字节 private int currentItem = 0; // 正在上传第几个文件 private long startTime=System.currentTimeMillis(); //开始上传的时间,用于计算上传的速度 public long getStartTime() { return startTime; } public void setStartTime(long startTime) { this.startTime = startTime; } public long getReadedBytes() { return readedBytes; } public void setReadedBytes(long readedBytes) { this.readedBytes = readedBytes; } public long getTotalBytes() { return totalBytes; } public void setTotalBytes(long totalBytes) { this.totalBytes = totalBytes; } public int getCurrentItem() { return currentItem; } public void setCurrentItem(int currentItem) { this.currentItem = currentItem; } }
把监听器FileUploadListener 添加到MyJakartaMultiPartRequest类中。MyJakartaMultiPartRequest类是Struts2源码中的JakartaMultiPartRequest类。
在此类中添加进度监听器,并覆盖此类。
private List<FileItem> parseRequest(HttpServletRequest servletRequest, String saveDir) throws FileUploadException { /* FileState fileState=new FileState(); servletRequest.getSession().setAttribute("state", fileState);*/ DiskFileItemFactory fac = createDiskFileItemFactory(saveDir); ServletFileUpload upload = new ServletFileUpload(fac); upload.setSizeMax(maxSize); // add 设置进度监听器 upload.setProgressListener(new FileUploadListener(servletRequest)); // end return upload.parseRequest(createRequestContext(servletRequest)); }
在xml中配置
<!-- 配置自定义文件类myrefactor,继承MultiPartRequest重写 --> <bean type="org.apache.struts2.dispatcher.multipart.MultiPartRequest" name="myrefactor" class="com.service.MyJakartaMultiPartRequest" scope="default" optional="true" />
action
public class FileProgressAction { /** * 显示文件上传的进度 */ public String execute(){ HttpServletResponse response= ServletActionContext.getResponse(); response.setHeader("Cache-Control", "no-store"); //禁止浏览器缓存 response.setHeader("Pragrma", "no-cache"); //禁止浏览器缓存 response.setDateHeader("Expires", 0); //禁止浏览器缓存 Map session=ActionContext.getContext().getSession(); PrintWriter out = null; try { out = response.getWriter(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } FileState status = (FileState)session.get("state"); if(status == null){ //renderText("error"); return null; } long startTime = status.getStartTime(); //上传开始时间 long currentTime = System.currentTimeMillis(); //现在时间 long time = (currentTime - startTime)/ 1000 + 1; //已传输的时间 单位:s //传输速度单位:byte/s double velocity = ((double)status.getReadedBytes()) / (double)time; //估计总时间 double totalTime = status.getTotalBytes(); //估计剩余时间 double timeLeft = totalTime - time; //已经完成的百分比 int percent = (int)(100 * (double)status.getReadedBytes() / (double)status.getTotalBytes()); //已经完成数单位:m double length = ((double) status.getReadedBytes())/1024/1024; //总长度 单位:m double totalLength = ((double) status.getTotalBytes())/1024/1024; JSONObject json = new JSONObject(); json.put("percent", percent); json.put("length", length); json.put("totalLength", totalLength); json.put("velocity", velocity); json.put("time", time); json.put("totalTime", totalTime); json.put("timeLeft", timeLeft); json.put("fileNumber", status.getCurrentItem()); // System.out.println(json.toString()); out.print(json.toString()); return null; } }
js
var finished = true; //上传是否结束 function showStatus(){ finished = false; /*$('#progressBarItem').attr('width','1%');*/ setTimeout('callback()',100); } function callback(){ if(finished) return; var url = 'fileProgressAction'; $.get(url,function(dataSrc){ var dataS=eval("("+dataSrc+")"); $('#progressBarItem').html("("+dataS.percent+"%"+")"); //alert(dataS.percent); }); setTimeout('callback()',100); }
jsp
<div style=" 86px;float: left;margin-top: 15px;margin-left: 5px;"> <form action="filesUpload" method="post" enctype="multipart/form-data" style="margin-top: 16px;" onsubmit="return subClick()" > <a href="javascript:;" class="file"> <img alt="tip" src="images/upload.png" style=" 55px;"> <input type="file" name="myFile" multiple="multiple" id="myFile" value="0" onchange="uplaodfileOnChange(this)"> </a> <input type="submit" value="上传文件" style="margin-top: 3px;display: none;" id="sub" class="a-upload" onclick="wait()" /> <div id="fileDiv"></div> <div style="margin-left: 7px;margin-top: 3px; 300px;" id="messageDiv" class="tip">${message} </div> <%-- <span class="tip" id="perMessage"> ${request.perMessage} </span> --%> </form> <div id="error" class="tip" style=" 1024px;"> <s:fielderror> </s:fielderror></div> </div>