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

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


前端相关代码:









相关的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"


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

   
          2097152
          UTF-8 
     



后台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 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 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 paramMap = new HashMap();
		    	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

    
	  
	      
	      
	      
	      
	      
	      
	      
	      
	      
	      
	          
	      
	 


最后是相应获取进度的请求,从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;
	}


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

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


你可能感兴趣的:(前端)