ITPub博客

首页 > 应用开发 > Java > Java web 中实现 文件上传 进度条显示

Java web 中实现 文件上传 进度条显示

原创 Java 作者:self_control 时间:2015-08-17 09:31:47 0 删除 编辑

请客官参考http://blog.itpub.net/30066956/viewspace-1775286/ 这一篇文章,来决定使用哪儿种,个人觉得使用uploadify更好更方便。

感谢:http://blog.sina.com.cn/s/blog_674b23220100he8x.html ,本文参考了很多这篇博文中的内容。
摘要:

         web项目中,经常会有文件上传需求。有时会遇到上传很大的文件,需要时间比较长。这样如果在界面上给用户一个进度条展示上传进度,会大大增加用户使用的方便。

本文介绍了使用struts进行文件上传时,前台进度显示的一种解决方案。

 

关键词:Struts2  进度条  文件上传 progressbar  easyui

 

问题及目标:在数据分析平台项目中,有一个功能是数据上传。这个功能主要是为用户提供一个功能,把本地的数据文件上传到服务器上,以便进行后续的数据分析。数据文件大小限制为2G,实际用户上传的数据文件大小一般也不会太小,再加上如果网速慢的话,等待时间可能会很长。所以要为这个功能加上进度条,让用户在等待过程中, 了解自己数据上传进度。

先上效果图

       

解决步骤。

1、  前台进度条控件选择使用easyui progressbar控件。

详细的使用说明参考官网文档:http://www.jeasyui.com/documentation/index.php

所有需要引入jquery-1.11.1.min.js 以及jquery.easyui.min.js

2、 前台显示控件有了,下面需要提供一个后台方法,来供前台查询上传进度。(使用Struts2自带的文件上传,它集成了commons-fileupload)

3、 在上传文件时,不断的向后台请求目前的进度,改变进度条控件的值。

实现监控到文件上传进度

下面的重点在于如何使用commons-fileupload进行文件上传时使用进度。

http://commons.apache.org/proper/commons-fileupload/using.html 在这个官方文档中搜索 Watching progress 可以得到详细的指导。


点击(此处)折叠或打开

  1. //Create a progress listener
  2. ProgressListener progressListener = new ProgressListener(){
  3.    public void update(long pBytesRead, long pContentLength, int pItems) {
  4.        System.out.println("We are currently reading item " + pItems);
  5.        if (pContentLength == -1) {
  6.            System.out.println("So far, " + pBytesRead + " bytes have been read.");
  7.        } else {
  8.            System.out.println("So far, " + pBytesRead + " of " + pContentLength
  9.                               + " bytes have been read.");
  10.        }
  11.    }
  12. };
  13. upload.setProgressListener(progressListener);

先创建一个实现了ProgressListener接口的对象,然后对upload对象发出增加监听器消息。

但问题是,我们是使用了Struts2 进行文件上传。而Struts2在文件上传的处理的类过程中并没有为我们加一个这样的监听器。

解决办法:(参考http://blog.sina.com.cn/s/blog_674b23220100he8x.html)

找到org.apache.struts2.dispatcher.multipart.JakartaMultiPartRequest类的代码。

自己写个类实现MyMultiPartRequest

org.apache.struts2.dispatcher.multipart.JakartaMultiPartRequest的代码copy进来再修改parseRequest 这个方法的实现,加上监听部分。把进度信息放到Session中

 

这是我的项目中修改后的parseRequest方法。


点击(此处)折叠或打开

  1. private List<FileItem> parseRequest(HttpServletRequest servletRequest,
  2.             String saveDir) throws FileUploadException {

  3.         UploadStatus status = new UploadStatus(); // 上传状态
  4.         UploadListener listner = new UploadListener(status); // 监听器
  5.         servletRequest.getSession().setAttribute("uploadStatus", status); // 把状态放到session里去

  6.         DiskFileItemFactory fac = createDiskFileItemFactory(saveDir);
  7.         ServletFileUpload upload = new ServletFileUpload(fac);
  8.         upload.setSizeMax(maxSize);
  9.         upload.setProgressListener(listner);// 添加监听器

  10.         return upload.parseRequest(createRequestContext(servletRequest));
  11.     }

UploadListener 类代码


点击(此处)折叠或打开

  1. public class UploadListener implements ProgressListener {

  2.     private UploadStatus status;

  3.     public UploadListener(UploadStatus status) {
  4.         this.status = status;
  5.     }

  6.     public void update(long bytesRead, long contentLength, int items) {
  7.         // 上传组件会调用该方法
  8.         status.setBytesRead(bytesRead); // 已读取的数据长度
  9.         status.setContentLength(contentLength); // 文件总长度
  10.         status.setItems(items); // 正在保存第几个文件
  11.         
  12.     }
  13. }

点击(此处)折叠或打开

  1. public class UploadStatus {

  2.     private long bytesRead; // 已经上传的字节数,单位:字节
  3.     private long contentLength; // 所有文件的总长度,单位:字节
  4.     private int items; // 正在上传第几个文件
  5.     private long startTime = System.currentTimeMillis(); // 开始上传的时间,用于计算上传速度等
  6.     public long getBytesRead() {
  7.         return bytesRead;
  8.     }
  9.     public void setBytesRead(long bytesRead) {
  10.         this.bytesRead = bytesRead;
  11.     }
  12.     public long getContentLength() {
  13.         return contentLength;
  14.     }
  15.     public void setContentLength(long contentLength) {
  16.         this.contentLength = contentLength;
  17.     }
  18.     public int getItems() {
  19.         return items;
  20.     }
  21.     public void setItems(int items) {
  22.         this.items = items;
  23.     }
  24.     public long getStartTime() {
  25.         return startTime;
  26.     }
  27.     public void setStartTime(long startTime) {
  28.         this.startTime = startTime;
  29.     }
  30.     
  31. }

还需要配置一下,让Struts2使用我们自己写的MyMultiPartRequest


点击(此处)折叠或打开

  1. <constant name="struts.multipart.parser" value="com.hengyun.action.uploadprocess.MyMultiPartRequest" />
  2. <constant name="struts.multipart.handler" value="com.hengyun.action.uploadprocess.MyMultiPartRequest" />
  3. <constant name="struts.multipart.maxSize" value="2000000000"/>

取得进度信息

经过上面的工作,现在在上传文件时,Session已经有了UploadStatus 对象了。

可以实现一个action,从Session中取进度信息,返回前台。

项目中action 代码,可以用做参考



点击(此处)折叠或打开

  1. /**
  2.      * 显示文件上传的进度
  3.      */
  4.     public String getFileUploadProgress(){
  5.         ActionContext cxt = ActionContext.getContext();
  6.         HttpServletResponse response = (HttpServletResponse)cxt.get(ServletActionContext.HTTP_RESPONSE);
  7.         
  8.         UploadStatus status = (UploadStatus)SessionUtil.getObjectFromSession("uploadStatus");
  9.         
  10.         if(status == null){
  11.             return "fail";
  12.         }
  13.         
  14.         long startTime = status.getStartTime(); //上传开始时间
  15.         long currentTime = System.currentTimeMillis(); //现在时间
  16.         long time = (currentTime - startTime)/ 1000 + 1; //已传输的时间 单位:s
  17.         
  18.         //传输速度单位:byte/s
  19.         double velocity = ((double)status.getBytesRead()) / (double)time;
  20.         //估计总时间
  21.         double totalTime = status.getContentLength();
  22.         //估计剩余时间
  23.         double timeLeft = totalTime - time;
  24.         //已经完成的百分比
  25.         int percent = (int)(100 * (double)status.getBytesRead() / (double)status.getContentLength());
  26.         //已经完成数单位:m
  27.         double length = ((double) status.getBytesRead())/1024/1024;
  28.         //总长度 单位:m
  29.         double totalLength = ((double) status.getContentLength())/1024/1024;
  30.         
  31.         ret.put("percent", String.valueOf(percent));
  32.         ret.put("length", String.valueOf(length));
  33.         ret.put("totalLength",String.valueOf( totalLength));
  34.         ret.put("velocity", String.valueOf(velocity));
  35.         ret.put("time", String.valueOf(time));
  36.         ret.put("totalTime", String.valueOf(totalTime));
  37.         ret.put("timeLeft", String.valueOf(timeLeft));
  38.         ret.put("fileNumber", String.valueOf(status.getItems()));
  39.         return "success";
  40. }


前台展现

把我写的一个demo贴上来,以供参考吧。

点击(此处)折叠或打开

  1. <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
  2. <%
  3. String path = request.getContextPath();
  4. String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
  5. %>

  6. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
  7. <html>
  8.  <style type="text/css">
  9.  #progressBar{width:400px;height:12px;background:#FFFFFF;border:1px solid #000000; padding: 1px;}
  10.  #progressBarItem{width:0%; height:100%;background:#FF0000}
  11.  </style>
  12.  <link rel="stylesheet" type="text/css" href="css/easyui.css">
  13.  <link rel="stylesheet" type="text/css" href="css/demo.css">
  14.  <link rel="stylesheet" type="text/css" href="css/icon.css">
  15.  

  16.  <script type="text/javascript" src="js/jquery-1.11.1.min.js"></script>
  17.  <script type="text/javascript" src="js/jquery.easyui.min.js"></script>
  18.  <script type="text/javascript" src="js/json/json_parse_state.js"></script>
  19.   <script type="text/javascript" src="js/main.js"></script>
  20.  
  21.  
  22.  
  23.  
  24.  <script>
  25.          function showUploadProgress(processbarid){
  26.             var url ='test/test_doFileProgress.action?radom='+Math.random();
  27.             var dataObj = $.ajax({
  28.                     url : url,
  29.                     async : false
  30.             });
  31.     
  32.             var myObject = json_parse(dataObj.responseText);
  33.             $("[id="+processbarid+"]").progressbar('setValue', myObject.percent);
  34.             setTimeout(arguments.callee, 500);
  35.         };
  36.         
  37.         function uploadData() {
  38.             showUploadProcess("fileuploadprocessbar")
  39.             $('#uploadData').form('submit', {
  40.                 url : 'data/dataAction_saveData.action',
  41.                 success : function(data) {
  42.                         $('#uploadData').form('clear');
  43.                 }
  44.             });
  45.         }
  46. </script>
  47.  </head>
  48.    <body>
  49.         <form id="uploadData" method="post" action="data/dataAction_saveData.action" enctype="multipart/form-data"">
  50.         
  51.         <div class="content">
  52.            <table border="0" cellspacing="1" cellpadding="0" width="100%" class="tk_table">
  53.               <tr>
  54.                 <td>文件上传:</td>
  55.                 <td><input type="file" name="file" size="28" /></td>
  56.               </tr>
  57.               <tr>
  58.               <td>进度<td/>
  59.               <td><div id="fileuploadprocessbar" class="easyui-progressbar" style="width:400px;background-color:'ff0000'"></div> </td>
  60.                </tr>
  61.            </table>
  62.         </div>
  63.         <div class="bottombtn">
  64.             <table width="40%" class="btntalbe">
  65.                 <tr>
  66.                     <td align="center">
  67.                         <input id="btnOk" type="submit" value="确定" class="tkbtn surebt" onclick="uploadData()"/></td>
  68.                     <td align="center">
  69.                         <input type="button" class="closeB tkbtn" value="取消


如何使用

    在任何一个需要进度条显示上传文件进度的地方只要在提交之前加一行代码就可以了!only one.它就是 :

        showUploadProgress(processbarid);

    processbarid 为前台processbar 控件的id。


来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/30066956/viewspace-1773697/,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2014-12-16

  • 博文量
    49
  • 访问量
    373390