您的位置 首页 java

手把手教你实现超大数据量带进度条导入导出功能(一导入篇)

概述

数据入导出功能是程序员开发中比较常见的功能,操作 导入导出 的人为业务人员,大批量数据的导入导出往往需要长时间的等待,为了让操作人员对导入导出进度直观可见,为导入导出功能添加进度条就是的该功能的使用体验有值得提升。

效果演示

开发流程

  1. 在“上传” 按钮下方编写静态进度条html代码,默认为隐藏状态
 <div id="progress" style="height:20px;width:100%;background: #efefef;border:1px solid #eee;border-radius:10px;display:none;">
    <div class="bar" style="background: green;width:10%;height: 100%;border-radius:10px; line-height :20px;">0%</div>
</div>  

效果如下:

说明:具体使用时通过动态修改内部div的宽度即可实现进度条的变化。

  1. 在文件上传Form表单内添加taskId隐藏框,完整html代码如下:
 <button style="width: 100px;" onclick=" Upload ()" id="uploadBtn">上传</button>    (仅限 CSV 格式)<br><br>
<div id="progress" style="height:20px;width:100%;background: #efefef;border:1px solid #eee;border-radius:10px;">
    <div class="bar" style="background: green;width:10%;height: 100%;border-radius:10px;line-height:20px;">0%</div>
</div>
<form id=" file Form" enctype="multipart/form-data">
    <input type="file" accept="text/csv" style="display: none;" id="fileInput" onchange="onFileChange()" name="upLoadFile">
    <input type="hidden" id="taskId" name="taskId">
</form>  

说明: 添加taskId用来标识本次上传的任务唯一性

  1. 编写文件上传js代码

文件上传开始初始化进度条展示,进度为零,然后开启一个定时任务定时更新上传进度,进度值通过后台接口获取。代码如下:

 function upload(){
   $('#fileInput').click()
}
function onFileChange(){
   var bar =$('#progress').show().find('.bar')
   bar.text('0%')
   bar.css({width:'0%'});
   var taskId = ''+ new Date().getTime()
   $('#taskId').val(taskId)
   timer = setInterval(function(){
       $.ajax({
           type:'post',
           url:'getProgress',
           data:{taskId:taskId},
           dataType: "json",
       }).success(function(data){
           if(data.result){
               bar.text(data.value + '%')
               bar.css({width:data.value + '%'})
           }
       }).error(function(e){
       })
   },2000);
   $.ajax({
       type:'post',
       url:'upload',
       data:new FormData($('#fileForm')[0]),
       cache: false,
       processData: false,
       contentType: false,
   }).success(function(data){
       clearInterval(timer)
       $('#progress').hide().find('.bar').css({width:'0%'})
       // do some things
   }).error(function(e){
       clearInterval(timer)
       $('#progress').hide().find('.bar').css({width:'0%'})
       // do some things
   })
},  
  1. 编写 Java 处理上传业务代码

主要逻辑为,获取文件总条数,然后循环读取记录分批处理,同时更新任务进度(已经处理记录数占总条数的百分比)入内存(集群环境可以存入中间件如redis),key为taskId,value为百分比值。

 public  void  execute() throws  Exception {
     json Object jsonObject = new JSONObject();
    jsonObject.put("result",true);
    jsonObject.put("msg","成功");
    UploadFile upLoadFile = getFile("upLoadFile","/", integer .MAX_VALUE);
    final File file = upLoadFile.getFile();
    final int lineNumber;
    // 获取文件总条数
    try (final FileReader in1 = new FileReader(file); final LineNumberReader lineNumberReader = new LineNumberReader(in1)){
        lineNumberReader.skip(file.length());
        lineNumber = lineNumberReader.getLineNumber();
    }
    final String username = getUsername();
    final String taskId = getPara("taskId");
    int sum = 0;
    final Pattern compile = Pattern.compile("1\d{10}");
    try(final FileReader in = new FileReader(file); final BufferedReader reader = new BufferedReader(in);){
        String str;
        List<String> mobileList =new ArrayList<>();
        while ((str = reader.readLine()) != null){
            String mobile = str.trim().split(",")[0];
            if(!compile.matcher(mobile).matches()){
                jsonObject.put("result",false);
                jsonObject.put("msg","手机号格式不正确("+mobile+")");
                continue;
            }
            mobileList.add(mobile);
            if(mobileList.size() == 100){
                int num = remoteUploadUser(mobileList,username);
                mobileList.clear();
            }
            sum ++;
            taskProgressMap.put(taskId,sum * 100/lineNumber);
        }
        if(!mobileList.isEmpty()){
            int num = remoteUploadUser(mobileList,username);
            mobileList.clear();
        }
    }catch (Exception e){
        jsonObject.put("result",false);
        jsonObject.put("msg","系统错误:" + e.getMessage());
    }
    jsonObject.put("count",count);
    renderJson(jsonObject.toJSONString());
}

public void getProgress(){
    JSONObject jsonObject = new JSONObject();
    jsonObject.put("result",true);
    jsonObject.put("msg","成功");
    final String taskId = getPara("taskId");
    final Integer integer = taskProgressMap.get(taskId);
    if(integer == null){
        jsonObject.put("result",false);
        jsonObject.put("msg","失败");
    }
    jsonObject.put("value",integer);
    renderJson(jsonObject.toJSONString());
}  

总结

  1. 超大数据文件处理需要分批处理。
  2. 前端组件需要先编写静态页面,然后将其动态化

文章来源:智云一二三科技

文章标题:手把手教你实现超大数据量带进度条导入导出功能(一导入篇)

文章地址:https://www.zhihuclub.com/184060.shtml

关于作者: 智云科技

热门文章

网站地图