首页 > 代码库 > 数据导入与实时进度条实现

数据导入与实时进度条实现

digiflow数据导入与实时进度条实现

 

本文档只是稍微解析下数据导入的流程,以及讲解实时进度条实现方法

 

数据批量导入流程

1、客户把.txt数据打包成.gz文件,发给我们。

GZ文件格式,每个文件的第一行是唯一的数据,导入完成后要插入到ImportRecord

名字格式:DigiFlow_南宁 - 平安出单中心_20100201_000100ECHW8P8708.txt

内容格式:以”||”为分割符

比如:00||000100ECHW8P8708||8||18:08:17

00代表表名称

000100ECHW8P8708 代表这个文件的唯一标识

 

2JAVA解压缩GZ文件

JAVA提供了GZIPInputStream 解压API,把里面的内容写入到txt文件里。

 

3、解压的文件临时存放目录

一种是在安装的TOMCAT根目录下新建file目录,然后System.getProperty("user.dir") + "/file/"

二种是System.getProperty("java.io.tmpdir")得到的是tomcat的临时目录

项目中用到的是第一种

 

4读取解压的文件

if("00".equals(fileinfos[0]))  读取到第一行时,根据UID判断是否导入过该文件。如果导入过则系统提示,并删除解压的文件。如果没有导入过,则继续执行下一步直到导入完成,完成后再插入这个文件的唯一标识。如:000100ECHW8P8708

 

读取到其他行时,获取其UID,判断是否插入过该记录。如果插入过,则执行update。如果没插入过,则执行insert.

 

5、拼SQL实现方式实现DMLinsertupdate

程序中的insertupdate语句是获得文件的中的列名之后,通过表名和列明去查找相应的字段信息,有的字段是varcharchardatetime型则加上‘’号。详细参见源码bossdataimportBusinessDAOImpl.java类的getStringType()方法。

 

 

 

 

AJAX实现实时WEB进度条

我们为了改善用户界面,通常会在处理量大或者是网络速度较慢的时候,给用户显示一个处理进度,让用户心理有底,增强用户等待结果的耐心,以改善用户体验。为了达到这个效果,通常做法有两大类:简单等待和真实的处理进度,本文着重讨论第二种方法的实现。

 

1)简单的等待界面:这种做法之所以说简单,就是在用法发送了处理命令后,立即在页面的某个地方替换一个waiting的图片,比如一个转圈的GIF,一张Loading的图片等,这种不称之为进度条,顶多就是个等待条,但通常还是可以给用户带来那么点满足,在业务量不大的情况下,也够用了,例子参见http://www.belitastone.com的首页。

 

2)真实的等待进度:比如说,我要在B/S系统中实现一个数据导入的功能,数据文件总共有100个,每个文件包含成千上万的数据,导入过程可能需要15分钟,那么我还用一个图片在那边打转吗?现在这样还是不够的,我可能需要让使用者知道,我当前处理的是第几个文件,还剩下几个,处理的百分比,并显示一个加载的真实进度条,这个进度条要如实反映处理的百分比。

 

实现1:由于用户处理的数据量大,可以在文件导入过程中,循环计算进度,并将进度信息存储在上下文中,并在前台页面定时从上下文读取进度数据,并在页面显示。这种方法思路比较直接。

 

实现2:使用观察者模式,实现进度主动通知。思路是:在文件导入过程中,计算进度信息,并将进度数据通知给观察者,前台页面定时向观察者咨询进度,并将进度显示到页面中。

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/zhengtanyun/archive/2009/07/06/4325528.aspx

 

 

我来说下我的实现方式

关于他说的“实现1”,说把进度信息存储到上下文,这个貌似有问题,这个上下文是servlet上下文?据我所知,上下文作用域和Application作用域一样大,进度条每个用户执行不同的导入操作,存到上下文做什么,还不乱套?

 

我的实现方式和“实现2”有点像。思路是:在文件导入过程中,循环计算进度信息,并将进度数据放入SESSION,前台页面通过AJAX定时调用,获取进度,并将进度显示到页面中.

进度数据有:总的数据量、已导入数据量、已经上传时间。

 

另外一种情况:当正在进行导入时,点击了别的页面,从而页面上的进度条就没有了,而后台却还在运行。有几种方法,一是弹出模式对话框,在模式框里面进行导入,但是这样还有点麻烦。二是当用户点击了别的页面再回到导入页面时,又重新读取SESSION中的进度信息。这需要在ACTION中设置一个全局变量来作为是否正在执行导入操作的标记。

 

 

 

最终效果图:(见附件) 

 效果图

 

 

代码实现参考源代码manage中的DigimpAction.java以及dimpImport.jsp

核心代码如下:

ACTION 部分代码

Java代码  收藏代码

  1. <strong>//  读取数据导入实时状态  

  2.     public ActionForward doStatus(ActionMapping mapping, ActionForm form,  

  3.             HttpServletRequest request, HttpServletResponse response) throws Exception  

  4.     {  

  5.         // 设置该响应不在缓存中读取  

  6.         response.addHeader("Expires""0");  

  7.         response.addHeader("Cache-Control",  

  8.                 "no-store, no-cache, must-revalidate");  

  9.         response.addHeader("Pragma""no-cache");  

  10.         response.setHeader("Cache-Control""no-cache");  

  11.         response.setCharacterEncoding("utf-8");            

  12.         response.setContentType("text/html; charset=utf-8");            

  13.         int totalSize = 0;// 总数据的条数  

  14.         int bytesRead = 0;// 已导入数据条数  

  15.         long getElapsedTimeInSeconds=0;// 获得已经上传得时间  

  16.         HttpSession session = request.getSession(false);  

  17.         if (session.getAttribute("TOTALSIZE")  != null) {  

  18.             if(count == 0){  

  19.                 session.removeAttribute("TOTALSIZE");  

  20.             }else{  

  21.                 totalSize=Integer.parseInt(session.getAttribute("TOTALSIZE").toString());  

  22.                   

  23.             }  

  24.         }  

  25.         if (session.getAttribute("BYTESREAD")  != null) {  

  26.             if(count == 0){  

  27.                 session.removeAttribute("BYTESREAD");  

  28.             }else{  

  29.                 bytesRead=Integer.parseInt(session.getAttribute("BYTESREAD").toString());  

  30.             }  

  31.         }  

  32.         if (session.getAttribute("STARTTIME")  != null) {  

  33.             long stime=Long.parseLong((String)session.getAttribute("STARTTIME"));  

  34.             getElapsedTimeInSeconds=(System.currentTimeMillis() - stime) / 1000;  

  35.         }  

  36.           

  37.         //计算上传完成的百分比  

  38.         String percentComplete="0";  

  39.         if(totalSize > 0){  

  40.             double k = (double)bytesRead/totalSize*100;   

  41.             BigDecimal big=new BigDecimal(k);    

  42.             percentComplete = big.setScale(2,BigDecimal.ROUND_HALF_UP).toString();   

  43.         }  

  44.         //获得上传已用的时间  

  45.         long timeInSeconds = getElapsedTimeInSeconds;  

  46.         //计算平均上传速率  

  47.         //double uploadRate = bytesRead / (timeInSeconds + 0.00001);  

  48.         //System.out.println("**************计算平均上传速率="+bytesRead);  

  49.         // 计算总共所需时间  

  50.         //double estimatedRuntime = totalSize / (uploadRate + 0.00001);  

  51.           

  52.         //将上传状态返回给客户端  

  53.         response.getWriter().println("<b>Import Status:</b><br/>");  

  54.         if (bytesRead != totalSize) {  

  55.             response.getWriter().println(  

  56.                     "<div class=\"prog-border\"><div class=\"prog-bar\" style=\"width: "  

  57.                             + percentComplete + "%;\"></div></div>");  

  58.             response.getWriter().println(  

  59.                     "Imported: " + bytesRead + " out of " + totalSize  

  60.                             + " Records (" + percentComplete + "%) <br/>");  

  61.             response.getWriter().println(  

  62.                     "Runtime: " + formatTime(timeInSeconds) + " <br/>");  

  63.         } else {  

  64.             response.getWriter().println(  

  65.                     "Imported: " + bytesRead + " out of " + totalSize  

  66.                             + " Records<br/>");  

  67.             response.getWriter().println("Complete.<br/>");  

  68.         }  

  69.         //如果文件已经导入完毕  

  70.         if (bytesRead == totalSize) {  

  71.             response.getWriter().println("<b>Imported complete.</b>");  

  72.         }  

  73.         return null;  

  74.     }  

  75.     private String formatTime(double timeInSeconds) {  

  76.         long seconds = (long) Math.floor(timeInSeconds);  

  77.         long minutes = (long) Math.floor(timeInSeconds / 60.0);  

  78.         long hours = (long) Math.floor(minutes / 60.0);  

  79.   

  80.         if (hours != 0) {  

  81.             return hours + "hours " + (minutes % 60) + "minutes "  

  82.                     + (seconds % 60) + "seconds";  

  83.         } else if (minutes % 60 != 0) {  

  84.             return (minutes % 60) + "minutes " + (seconds % 60) + "seconds";  

  85.         } else {  

  86.             return (seconds % 60) + " seconds";  

  87.         }  

  88.     }  

  89.     //页面调用此方法,检查导入工作是否正在进行时,0:无 1:正在进行  

  90.     public int checkImportStatus(){  

  91.         return count;  

  92.     }  

  93. </strong>  

 

 

 

 

dimpImport.jsp  部分代码

Java代码  收藏代码

  1. <script type="text/javascript">  

  2.     var xmlHttp;   

  3.     function createXMLHttpRequest()//创建XMLHttpRequest对象   

  4.     {   

  5.         if(window.ActiveXObject){   

  6.             xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");   

  7.         }else if(window.XMLHttpRequest){   

  8.             xmlHttp = new XMLHttpRequest();   

  9.         }   

  10.     }   

  11.     //导入程序入口  

  12.     function tijiao(){  

  13.         document.forms[0].action=" ";  

  14.         document.forms[0].submit();  

  15.         go();  

  16.     }  

  17.     function go()   

  18.     {  

  19.         createXMLHttpRequest();//创建XMLHttpRequest对象  

  20.         xmlHttp.onreadystatechange = callBack;//设置回调函数   

  21.         var url = "digimp.do?method=doStatus";//请求的地址   

  22.         var button = document.getElementById("go");   

  23.         button.disabled = true;//设置按钮不可用   

  24.         xmlHttp.open("post",url,true);//打开对服务器的连接   

  25.         xmlHttp.send();//发送请求   

  26.     }   

  27.     function callBack()   

  28.     {   

  29.         if(xmlHttp.readyState == 4){   

  30.             if(xmlHttp.status == 200){  

  31.                 setTimeout("go()",500);//定时调用  

  32.                 document.getElementById(‘status‘).innerHTML =xmlHttp.responseText;  

  33.             }   

  34.         }   

  35.     }  

  36.     //检查是否有正在进行的导入操作  

  37.     function page_init(){  

  38.         DigimpAction.checkImportStatus(function callback_init(data){  

  39.             if(data != ‘0‘){  

  40.                 document.getElementById("go").disabled = true;  

  41.                 go();  

  42.             }else{  

  43.                 document.getElementById("go").disabled = false;  

  44.             }  

  45.         });  

  46.     }  

  47.       

  48. </script>  

  49. <body onload="page_init();">  

  50.         <!-- 这里显示进度条 -->  

  51. <div id="status"></div>  

  52. </body>  

 

  • 数据导入与进度条实现.rar (44.7 KB)

  • 描述: 文档以及代码

  • 下载次数: 511

  • 查看图片附件


数据导入与实时进度条实现