关于Easy UI中文件上传处理进度条的实现

简介: 关于Easy UI中文件上传处理进度条的实现

主要思路是用线程池池去处理上传任务,并计算上传进度,将进度保存到session中。前端通过一个定时器按固定时间调用获取进度条的百分比,更新进度条进度。



前端相关代码:



<script type="text/javascript" src="${pageContext.request.contextPath }/static/scripts/easyui/jquery.min.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath }/static/scripts/easyui/jquery.easyui.min.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath }/static/scripts/easyui/easyui-lang-zh_CN.js"></script>
<link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath }/static/scripts/easyui/themes/default/easyui.css">
<link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath }/static/scripts/easyui/themes/icon.css">
<link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath }/static/styles/common.css">
<link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath }/static/scripts/easyui/themes/demo.css">
<div id="progressDlg" class="easyui-dialog" title="执行进度" style="width: 600px;hight:400px;" data-options="iconCls:'icon-save',closed:true,resizable:true,modal:true,collapsible:true, buttons: '#progressDlgBtns'">
     <div style="padding: 10px 60px 20px 60px">
       <div id="p" class="easyui-progressbar" style="width:400px;"></div>
     </div>
  </div>
  <div id="progressDlgBtns" style="width: 600px;">
        <a href="javascript:void(0)" class="easyui-linkbutton" style="padding: 4px;" οnclick="javascript:$('#progressDlg').dialog('close')">关闭</a>
    </div>


相关的js代码:

//展示进度条
    var timerId;
    function showCheckProgress(){
      $('#progressDlg').dialog('open');
      //想要修改进度条的颜色去css文件中去修改  
       $('#p').progressbar({  
           value : 0,          //设置进度条值 默认0  
           text : '{value}%'  //设置进度条百分比模板 默认 {value}%  
           //在value改变的时候触发  
           /*onChange : function (newValue, oldValue) {  
               console.log('新:' + newValue + ',旧:' + oldValue);  
           },  */
       }); 
      timerId = window.setInterval(getCheckProgress,1000);
    }
    //通过post请求得到进度
    function getCheckProgress(){
      var progressUrl = $('#getProgressUrl').val();
         //使用JQuery从后台获取JSON格式的数据
         $.ajax({
          type:"post",//请求方式
          url:progressUrl,//发送请求地址
          timeout:3000,//超时时间:30秒
          dataType:"json",//设置返回数据的格式
          //请求成功后的回调函数 data为json格式
          success:function(data){
           if(data.progressValue>=100){
               window.clearInterval(timerId);
               $('#dg').datagrid('load');
               $('#importBtn').css('display','inline-block');
               $('#showProgress').css('display','none');
           }
           $('#p').progressbar('setValue',data.progressValue);
          },
          //请求出错的处理
          error:function(){
           window.clearInterval(timerId);
           //alert("请求出错");
          }
         });
    }


文件上传界面:enctype="multipart/form-data"


<div id="importDlg" class="easyui-dialog" title="批量导入" style="width:400px;padding:30px 70px 50px 70px">
      <form id="importForm" method="post"  enctype="multipart/form-data">
       <div style="margin-bottom:20px">
    <input id="uploadFile" class="easyui-filebox" name="uploadFile" data-options="prompt:'请选择要导入的文件……'" style="width:100%">
    </div>
    <div>
    <a href="#" id="doImportBtn"  class="easyui-linkbutton" style="width:100%">上传</a>
    <a href="#" id="cancelImportBtn"  class="easyui-linkbutton" style="width:100%">取消</a>
    </div>
   </form>  
  </div>


springmvc中对上传文件的通用属性配置:


<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">   
          <property name="maxUploadSize"><value>2097152</value></property>
          <property name="defaultEncoding"><value>UTF-8</value></property> 
    </bean>




后台java代码:

/**
  * 批量导入贷中记录
  */
  @RequestMapping(value = "/action/import")
  @ResponseBody
  public Result importList(HttpServletRequest request, HttpServletResponse response, @RequestParam MultipartFile uploadFile) {
  HttpSession session = request.getSession();
  session.setAttribute("progressValue", 0.0);
  Result result = new Result();
  try {
            String fileName = uploadFile.getOriginalFilename();
            long size = uploadFile.getSize();//文件大小,字节
            long maxSize =  2048000;//2M
            String fileType = StringUtils.split(fileName,".")[1];
            if(!StringUtils.equals(fileType, "xlsx") && !StringUtils.equals(fileType, "xls")){
              result.setCode(0);
        result.setMsg("请选择xlsx或xls格式的文件");
        return result;
            }
            if(size > maxSize){
              result.setCode(0);
        result.setMsg("批量导入的文件大小不能超过2M");
        return result;
            }
            String batchNo = "DZ" + DateUtil.getCurrentDateTime();
            List<RcsCreditManageJob> jobList = parseExcel( uploadFile.getInputStream(),session,batchNo);
            if(jobList!=null && jobList.size()>3000){
              result.setCode(0);
        result.setMsg("单次校验记录数不能超过3000");
        return result;
            }
            //先全部批量插入数据库
            rcsCreditManageJobServiceImpl.batchAdd(jobList);
            result = rcsCreditManageJobServiceImpl.batchCheckCreditIn(session,jobList,batchNo);
  } catch (Exception e) {
    result.setCode(0);
    result.setMsg("批量校验操作失败!");
    log.error("【批量校验操作异常】:"+ e.getMessage(),e);
  }
  return result;
  }



这里使用了多个线程,共同消费jobList中任务,每个Runnable中都传入了相同的对象progress来保存共同的信息,如批次号,总任务数,完成的任务数等。

/**
  * 批量校验
  */
  @Override
  public Result batchCheckCreditIn(HttpSession session,List<RcsCreditManageJob> jobList,String batchNo) {
  Result result = new Result();
  try {
    int totalSize = jobList.size();
    TaskProgress progress = new TaskProgress(totalSize,batchNo);
    for (RcsCreditManageJob job : jobList) {
    taskExecutor.execute(new dzCheckTask(progress,job,session));
    }
    result.setCode(1);
      result.setMsg("批量校验申请提交完毕!");
  } catch (Exception e) {
    e.printStackTrace();
    result.setCode(0);
      result.setMsg("批量校验申请提交失败!");
  }
  return result;
  }


/**
  * 执行校验的任务
  */
  private class dzCheckTask implements Runnable {
  private RcsCreditManageJob job;
  private TaskProgress progress;
  private HttpSession session;
  public dzCheckTask(TaskProgress progress,RcsCreditManageJob job,HttpSession session) {
    this.job = job;
    this.progress = progress;
    this.session=session;
  }
  public void run() {
    try {
        EngineCreditInDto ec = new EngineCreditInDto();
        ec.setName(job.getUserName());//用户名称
        ec.setMobile(job.getMobile());//手机号
        ec.setIdCard(job.getCertid());//身份证号
        ec.setCurrTime(DateUtil.getCurrentPrettyDateTime());//当前时间  
        ec.setCallType(job.getCallType());
        riskServiceFacade.evaluateCreditInCheck(ec);
        //根据表数据
        Map<String, Object> paramMap = new HashMap<String, Object>();
        paramMap.put("execTime", DateUtil.getCurrentDateTime());
        paramMap.put("certid", ec.getIdCard());
        paramMap.put("batchNo", progress.getTaskNo());
        rcsCreditManageJobMapper.updateExcuTimeByMap(paramMap);
        //更新进度
        session.setAttribute("progressValue", progress.computeProgress());
    Thread.sleep(200);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
  }
  }
/**
 * 任务进度实体
 */
public class TaskProgress {
   private int totalSize;//任务总数
   private int completeSize;//任务完成数
   private String taskNo;//任务批次
   public double taskProgress;//任务进度
  public TaskProgress(int totalSize, String taskNo) {
  this.totalSize = totalSize;
  this.taskNo = taskNo;
  }
    /**
     * 用同步代码块实现
     * 
     * @param money
     */
    public double computeProgress() {
        synchronized (this) {
          BigDecimal   b1   =   new   BigDecimal(Double.toString(this.getTotalSize())); 
          //没调用一次,完成一笔
          int newCompleteSize = this.getCompleteSize() + 1;
          this.setCompleteSize(newCompleteSize);
      BigDecimal   b2   =   new   BigDecimal(Double.toString(newCompleteSize));  
          double taskProgress = b2.divide(b1,2,RoundingMode.HALF_UP).multiply(new BigDecimal("100")).doubleValue();
          this.setTaskProgress(taskProgress);
          return taskProgress;
        }
    }
  public int getTotalSize() {
  return totalSize;
  }
  public void setTotalSize(int totalSize) {
  this.totalSize = totalSize;
  }
  public int getCompleteSize() {
  return completeSize;
  }
  public void setCompleteSize(int completeSize) {
  this.completeSize = completeSize;
  }
  public String getTaskNo() {
  return taskNo;
  }
  public void setTaskNo(String taskNo) {
  this.taskNo = taskNo;
  }
  public double getTaskProgress() {
  return taskProgress;
  }
  public void setTaskProgress(double taskProgress) {
  this.taskProgress = taskProgress;
  }
}


spring mvc中配置线程池的bean

<!-- 异步线程池-->  
  <bean id="taskExecutor"  
     class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">  
     <!-- 核心线程数 -->  
     <property name="corePoolSize" value="10" />  
     <!-- 最大线程数 -->  
     <property name="maxPoolSize" value="30" />  
     <!-- 队列最大长度 >=mainExecutor.maxSize -->  
     <property name="queueCapacity" value="3000" />  
     <!-- 线程池维护线程所允许的空闲时间 -->  
     <property name="keepAliveSeconds" value="300" />  
     <!-- 线程池对拒绝任务(无线程可用)的处理策略 -->  
     <property name="rejectedExecutionHandler">  
         <bean class="java.util.concurrent.ThreadPoolExecutor$CallerRunsPolicy" />  
     </property>  
  </bean>


最后是相应获取进度的请求,从session中获取最新的进度:


/**
  * 得到处理进度
  */
  @RequestMapping(value = "/action/getProgressValue")
  @ResponseBody
  public Map getProgressValue( HttpSession session) {
  double progress = (double) session.getAttribute("progressValue");
  Map map = new HashMap();
  map.put("progressValue", progress);
     return map;
  }

比较粗糙的实现,但是能跑能跳,本博客只是自己的工作记录之用,实现方式未必优雅。


如你有更好的方法,欢迎指教。


目录
相关文章
|
3月前
|
JSON 监控 数据格式
Easy UI datagrid的学习
Easy UI datagrid的学习
|
11月前
|
前端开发
Element-UI中的el-upload文件上传组件使用过程中踩的坑
Element-UI中的el-upload文件上传组件使用过程中踩的坑
|
开发框架 JavaScript 前端开发
ASP.NET Core WEB API 使用element-ui文件上传组件el-upload执行手动文件文件,并在文件上传后清空文件
ASP.NET Core WEB API 使用element-ui文件上传组件el-upload执行手动文件文件,并在文件上传后清空文件
436 0
ASP.NET Core WEB API 使用element-ui文件上传组件el-upload执行手动文件文件,并在文件上传后清空文件
|
JavaScript
关于各种Vue UI框架中加载进度条的正确使用
关于各种Vue UI框架中加载进度条的正确使用
|
Java
【鸿蒙 HarmonyOS】UI 组件 ( 进度条 ProgressBar 和 RoundProgressBar 组件 )(二)
【鸿蒙 HarmonyOS】UI 组件 ( 进度条 ProgressBar 和 RoundProgressBar 组件 )(二)
103 0
【鸿蒙 HarmonyOS】UI 组件 ( 进度条 ProgressBar 和 RoundProgressBar 组件 )(二)
【鸿蒙 HarmonyOS】UI 组件 ( 进度条 ProgressBar 和 RoundProgressBar 组件 )(一)
【鸿蒙 HarmonyOS】UI 组件 ( 进度条 ProgressBar 和 RoundProgressBar 组件 )(一)
187 0
【鸿蒙 HarmonyOS】UI 组件 ( 进度条 ProgressBar 和 RoundProgressBar 组件 )(一)