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

版权声明:本文为博主原创文章,创作不易,转载请注明出处。 https://blog.csdn.net/w1014074794/article/details/70210461

        主要思路是用线程池池去处理上传任务,并计算上传进度,将进度保存到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;" onclick="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;
	}


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

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


猜你喜欢

转载自blog.csdn.net/w1014074794/article/details/70210461
今日推荐