java excel导入获取实时进度

2019-10-25  本文已影响0人  东本三月

1.需求

2.实现思路

3.页面实现效果(仅供参考)

正在导入
导入完成

4.定义用于存储导入进度的对象

/**
 * 用于存储学生信息导入的进度信息
 * @author authstr
 * @time 2019年10月24日16:56:21
 */
public class ImportAsynInfo {

    //用于存储所有的导入进度信息
    public static Map<String,ImportAsynInfo> allAsynInfo=new HashMap<String,ImportAsynInfo>();

    //提示信息或 异常信息
    private String msg;
    //数据总数
    private Integer totality=0;
    //已处理的数据条数
    private Integer doneSum=0;
    //失败的数据条数
    private Integer errorSum=0;
    //成功的数据条数
    private Integer successSum=0;
    //错误文件的路径
    public String errorFilePath;
    //导入是否结束
    public  Boolean isEnd= false;

    /**
     * 创建一个进度信息,并获取对应的uuid
     * @return
     */
    public static String  createAsynInfo(){
        ImportAsynInfo asynInfo=new ImportAsynInfo();
        String uuid=UUID.randomUUID().toString().replace("-","");
        allAsynInfo.put(uuid,asynInfo);
        return uuid;
    }

    /**
     * 通过uuid获取进度信息
     * @param uuid
     * @return
     */
    public static ImportAsynInfo getAsynInfo(String uuid){
        return allAsynInfo.get(uuid);
    }

    /**
     * 通过uuid删除对应的进度信息
     * @param uuid
     * @return
     */
    public static void deleteAsynInfo(String uuid){
        allAsynInfo.remove(uuid);
    }

    /**
     * uuid对应的进度 已处理的数据条数+1
     * @param uuid
     */
    public static void doneSumAddOne(String uuid){
        ImportAsynInfo asynInfo= getAsynInfo(uuid);
        asynInfo.setDoneSum(asynInfo.getDoneSum()+1);
    }

    /**
     * uuid对应的进度 失败的数据条数+1
     * @param uuid
     */
    public static void errorSumAddOne(String uuid){
        ImportAsynInfo asynInfo= getAsynInfo(uuid);
        asynInfo.setErrorSum(asynInfo.getErrorSum()+1);
    }

    /**
     * uuid对应的进度 成功的数据条数+1
     * @param uuid
     */
    public static void successSumAddOne(String uuid){
        ImportAsynInfo asynInfo= getAsynInfo(uuid);
        asynInfo.setSuccessSum(asynInfo.getSuccessSum()+1);
    }

    public String getMsg() {
        return msg;
    }
    public void setMsg(String msg) {
        this.msg = msg;
    }
    public Integer getTotality() {
        return totality;
    }
    public void setTotality(Integer totality) {
        this.totality = totality;
    }
    public Integer getDoneSum() {
        return doneSum;
    }
    public void setDoneSum(Integer doneSum) {
        this.doneSum = doneSum;
    }
    public Integer getErrorSum() {
        return errorSum;
    }
    public void setErrorSum(Integer errorSum) {
        this.errorSum = errorSum;
    }
    public Integer getSuccessSum() {
        return successSum;
    }
    public void setSuccessSum(Integer successSum) {
        this.successSum = successSum;
    }
    public String getErrorFilePath() {
        return errorFilePath;
    }
    public void setErrorFilePath(String errorFilePath) {
        this.errorFilePath = errorFilePath;
    }
    public Boolean getEnd() {
        return isEnd;
    }
    public void setEnd(Boolean end) {
        isEnd = end;
    }

}

5.Controller层开启线程进行导入

@RestController
@RequestMapping("student_import/v1")
public class StudentImportController extends AbstractAPIController {
    @Autowired
    StudentImportServiceImpl studentImportService;

    private ExecutorService executor = Executors.newCachedThreadPool() ;

    //下载导入模板
    @RequestMapping("/excelExport")
    public void excelExport(HttpServletResponse response) {
        studentImportService.excelExport(response);
    }

     //数据导入处理
    @RequestMapping("/save_excel_auto_studentno")
    public Map saveExcelStudentno(HttpServletResponse response, @RequestParam("file") MultipartFile file){
        Map m = new HashMap<>();
        String uuid=ImportAsynInfo.createAsynInfo();
        try {
            final InputStream  inputStream = file.getInputStream();
            executor.submit(new Runnable(){
                @Override
                public void run() {
                    try {
                        studentImportService.saveExcel_auto_studentno(response, inputStream,uuid);
                    }catch(Exception e) {
                        e.printStackTrace();
                        ImportAsynInfo.getAsynInfo(uuid).setMsg(e.getMessage());
                        ImportAsynInfo.getAsynInfo(uuid).setEnd(true);
                        throw new Exception("无法进行导入!");
                    }
                }
            });
        } catch (IOException e) {
            e.printStackTrace();
        }
        m.put("uuid",uuid);
        return m;
    }
   //下载导入的错误文件
    @RequestMapping("downloadErrorExcel")
    public void downloadErrorExcel(HttpServletResponse response, String fileName){
        studentImportService.downloadErrorExcel(response, fileName);
    }

    //获取导入的进度
    @RequestMapping("get_import_plan")
    public Map get_import_plan(String uuid) {
        Map m = new HashMap<>();
        ImportAsynInfo asynInfo=ImportAsynInfo.getAsynInfo(uuid);
        //如果导入结束,复制进度对象进行返回,将储存的进度对象删除
        if(asynInfo!=null&&asynInfo.getEnd()){
            ImportAsynInfo newAsynInfo=new ImportAsynInfo();
            newAsynInfo.setEnd(asynInfo.getEnd());
            newAsynInfo.setMsg(asynInfo.getMsg());
            newAsynInfo.setErrorFilePath(asynInfo.getErrorFilePath());
            newAsynInfo.setTotality(asynInfo.getTotality());
            newAsynInfo.setDoneSum(asynInfo.getDoneSum());
            newAsynInfo.setErrorSum(asynInfo.getErrorSum());
            newAsynInfo.setSuccessSum(asynInfo.getSuccessSum());
            ImportAsynInfo.deleteAsynInfo(uuid);
            asynInfo=newAsynInfo;
        }
        m.put("data",asynInfo);
        return m;
    }

6. service进行执行导入

@Service
public class StudentImportServiceImpl extends AbstractService implements StudentImportService {

    @Override
    public void excelExport(HttpServletResponse response) {
           //导入模板下载   略  
     }

    @Override
    public void downloadErrorExcel(HttpServletResponse response, String fileName) {
          //下载错误文件   略  
    }


    @Transactional
    @Override
    public Map<String, Object> saveExcel(HttpServletResponse response, InputStream inputStream,String uuid) {
       //其他代码...
       //获取excel导入数据数量后
       ImportAsynInfo.getAsynInfo(uuid).setTotality( 数量 );
       //其他代码...
      for (int i = 0; i < 数量; i++) {
           //其他代码...
           //在一条数据处理结束后
           ImportAsynInfo.doneSumAddOne(uuid);
           //其他代码...
           if(数据有错误){
               //其他代码...
               ImportAsynInfo.errorSumAddOne(uuid);
           }else{
                //其他代码...
                ImportAsynInfo.successSumAddOne(uuid);
           }
       }
        //其他代码...
        //错误文件创建后
       ImportAsynInfo.getAsynInfo(uuid).setErrorFilePath(errorFileName);
        //其他代码...
        //导入完成后
        ImportAsynInfo.getAsynInfo(uuid).setEnd(true);
  }
}

7.显示进度条页面

<!doctype html>
<html>
<head>
        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
        <meta http-equiv="content-type" content="text/html;charset=utf-8">
        <meta content="always" name="referrer">
        <script src="/.../echarts/echarts.min.js"></script>
</head>
<body>
    <div class="J_conWarp g-lr-mg g-warning-box">
        <h4 class="g-title"> <a href="javascript:history.back()" style="font-size: 16px; color: black; " >< 返回</a></h4>
        <div class="J_containerWarp">
            <div  class="container-fluid g-t-mg2">
                <div class="row" >
                    <div class="col-xs-12" >
                            <div id="import_file">
                                <form class="form-horizontal" role="form" id="excelExportForm">
                                </form>
                                <form class="form-horizontal" role="form" id="downloadErrorExcelForm">
                                    <input type="hidden" name="fileName" id="fileName" value="" />
                                </form>
                                <form class="form-horizontal" role="form" id="form1">
                                    <div class="form-group ">
                                        <label class="col-xs-2 control-label"><em class="text-red">*</em>导入文件</label>
                                        <div class="col-xs-10">
                                            <input type="file" id="file" name="file" class="form-control" style="width:400px" accept=".xls" />
                                        </div>
                                    </div>

                                </form>
                                <div  class="form-group ">
                                    <label class="col-xs-2 control-label"></label>
                                    <a class="gbn gbn-m" href="javascript:" onclick="E.excelExport();" >下载导入模板</a>
                                    <a class="gbn gbn-m" href="javascript:" onclick="E.saveExcel();" >导入</a>
                                    <a class="gbn gbn-m gbn-red" href="javascript:" onclick="history.back();" >返回</a>
                                </div>
                            </div>

                            <!-- 为 ECharts 准备一个具备大小(宽高)的 DOM -->
                            <div id="main" style="width:100%;height:550px;"></div>
                            <div  id="downloadErrorExcelA"class="col-xs-12" style="height:150px;width:100%;display:none">
                            <div class="col-xs-4"></div>
                            <div  class="form-group ">
                                <a class="gbn gbn-m gbn-red"   href="javascript:" onclick="E.downloadErrorExcel();" >下载错误文件</a>
                                <a id="quxiao" class="gbn gbn-m"   href="javascript:" onclick="E.quxiao();" >取消</a>
                            </div>
                        </div>
                    </div>

                </div>

            </div>
        </div>

    </div>
</body>

<script type="text/javascript">
    window.onload = window.onresize = function() {
      $(".J_containerWarp").height($(window).height() - 60);
      $(".J_containerWarp").niceScroll({});
    }
    $.ajaxSettings.async=true;
    var uuid=null;
    var setInterval_id=null;
    var myChart = echarts.init(document.getElementById('main'));
    var option = {
        title : {
            text: '正在进行导入中...',
            subtext: '当前进度',
            x:'center'
        },
        tooltip : {
            trigger: 'item',
            formatter: "{a} <br/>{b} : {c} ({d}%)"
        },
        legend: {
            orient: 'vertical',
            left: 'right',
            data: ['导入成功','导入失败','未处理']
        },
        series : [
            {
                name: '导入进度',
                type: 'pie',
                // radius : '55%',
                radius: ['50%', '70%'],
                center: ['50%', '60%'],
                data:[
                    {value:0, name:'导入成功'},
                    {value:0, name:'导入失败'},
                    {value:100, name:'未处理'}
                ],
                itemStyle: {
                    emphasis: {
                        shadowBlur: 10,
                        shadowOffsetX: 0,
                        shadowColor: 'rgba(0, 0, 0, 0.5)'
                    }
                },
                color: ['#2ECC71','#E67E22','#BDC3C7'],
            }
        ]
    };
    var E = {
        excelExport : function() {
            $("form[id=excelExportForm]").attr("action",
                    "${request.contextPath}/student_import/v1/excelExport");
            $("#excelExportForm").submit();
        },
        saveExcel : function() {
            var file = $("#file").val();
            if(!file){
                Message.error("导入的文件不能为空");
                return ;
            }
            //循环获取进度信息
            setInterval_id=setInterval(E.getAsynInfo,500);
            myChart.setOption(option);
            var index = layer.load(1);
            var formData = new FormData();
            //隐藏导入区域和错误文件下载区域,显示进度条区域
            $("#import_file").hide();
            $("#main").show();
            $("#downloadErrorExcelA").hide();
            formData.append('file', $('#file')[0].files[0]);
             $.ajax({
                    type : "POST",
                    url : "${request.contextPath}/student_import/v1/save_excel",
                    data : formData,
                    async: false,
                    cache: false,
                    contentType: false,
                    processData: false,
                    success : function(o) {
                        if(o.code==1){
                            //设置uuid
                            uuid=o.uuid;
                        } else {
                            Message.error(o.msg);
                        }
                }
            });
        },
        downloadErrorExcel : function() {
            $("form[id=downloadErrorExcelForm]").attr("action",
                    "${request.contextPath}/student_import/v1/downloadErrorExcel");
            $("#downloadErrorExcelForm").submit();
        },
        getAsynInfo:function(){
            //如果uuid存在,进行获取数据
            if(uuid!=null){
                $.post("${request.contextPath}/student_import/v1/get_plan",{"uuid":uuid},function(o){
                    console.log(o);
                    //如果获取到了数据
                    if(o.code==1&&o.data!=null){
                        // 使用指定的配数据显示图表。
                        option.title.subtext="当前进度   [共"+o.data.totality+"]条";
                        option.series[0].data[0].value=o.data.successSum;
                        option.series[0].data[1].value=o.data.errorSum;
                        option.series[0].data[2].value=o.data.totality-o.data.doneSum;
                        myChart.setOption(option);
                        //如果导入结束了
                        if(o.data.isEnd){
                            option.title.text="导入完成";
                            myChart.setOption(option);
                            clearInterval(setInterval_id);
                            //如果有错误数据,展示错误文件的下载
                            if(o.data.totality>0&&o.data.errorSum>0){
                                $("#fileName").val(o.data.errorFilePath);
                                $("#downloadErrorExcelA").show();
                            }
                            //如果导入中出现的异常
                            if(o.data.msg!=null){
                                $("#import_file").show();
                                $("#main").hide();
                                Message.error(o.data.msg);
                            }else{
                                Message.success("导入结束,"+o.data.successSum+"条数据导入成功,"+o.data.errorSum+"条数据导入失败");
                            }
                        }
                    }else{
                        Message.error(o.msg);
                    }
                });
            }
        },
        quxiao:function () {
            $("#import_file").show();
            $("#main").hide();
            $("#downloadErrorExcelA").hide();
            uuid=null;
        }
    }

</script>

</html>

8.还未完成的功能

上一篇下一篇

猜你喜欢

热点阅读