生成进度条(动态生成文件,并前端显示生成进度)

来源:互联网 发布:如何通过网络定位找人 编辑:程序博客网 时间:2024/05/22 16:47

注:

1.本文是以生成txt文件为例子。
2.写的主要是一个思路,不一点非要是生成txt,可以是其他类型文件。
3.本文例子的项目地址:https://github.com/smallsnail-wh/wh

思路

  1. 在前端显示,需要拿到生成的进度(百分比)。
  2. 生成的进度为当前生成总量占需要生成总量的百分比。
  3. 需要生成的总量可以从前端输入得到(或者其他方式输入)。
  4. 当前生成总量在代码中设置计数变量得到。

我的实现方案

  1. 前端传生成总量到后端。
  2. 后端更具得到的生成总量生成txt。因为生成txt是耗时任务,所以启用线程生成。在线程中设置计数变量每生成一行数据,计数变量加1,并与生成总量计算出百分比。然后将百分比存入redis中。
  3. 在步骤2的同时,前端没个1秒或者2秒向后端发送请求,查询redis中存储的百分比。后端返回百分比,以供前端显示。
  4. 当百分比为100%后,前端发请求,删除redis中的数据。(为了防止下次生成不出错)
  5. 前端提供下载链接,以供下载。

实施

  1. 准备工作,我后端用了spring boot,数据库用redis代替(速度快),前端用了vue和基于Vue的UI组件库iview

  2. 网页代码如下:

    index.html

<!DOCTYPE html><html><head>    <meta charset="utf-8">    <title>mian</title>    <link rel="stylesheet" type="text/css" href="http://unpkg.com/iview/dist/styles/iview.css">    <script type="text/javascript" src="http://vuejs.org/js/vue.min.js"></script>    <script type="text/javascript" src="http://unpkg.com/iview/dist/iview.min.js"></script>    <script src="https://unpkg.com/axios/dist/axios.min.js"></script></head><body><div id="app">    <div style="text-align: center;margin-top: 200px">        <div style="margin-bottom: 25px;margin-top: 50px">            数量:            <i-input v-model="count" placeholder="请输入..." style="width: 200px"></i-input>            <strong style="color: rgb(210, 15, 15);margin-right: 25px">{{count/10000}}</strong>        </div>        <div>           <i-progress :percent="percent" style="width: 300px;margin-bottom: 25px"/>         </div>        <div>            <i-button v-if="codeCreate" type="primary" @click="create()" style="margin-left: 230px">生成</i-button>            <strong v-if="codeCreating" style="color: rgb(44, 204, 130);margin-left: 190px">正在生成TXT文件</strong>            <a :href="'temp/progress.txt'" download="download">                <i-button v-if="codeDownload" type="success" style="margin-left: 10px;margin-left: 230px">下载</i-button>            </a>        </div>    </div>  </div><script>    new Vue({        el: '#app',        data: {            /*用于展示的百分数*/            percent: 0,            /*控制组件是否显示*/            codeCreate: true,            /*控制组件是否显示*/            codeCreating: false,            /*控制组件是否显示*/            codeDownload: false,            /*需要生成的数量*/            count: null        },        mounted(){            console.log(axios.defaults);        },        methods: {            /*生成按钮的点击事件*/            create(){                var r = /^\+?[1-9][0-9]*$/;  //正整数                 if(r.test(this.count)){                    axios({                      method: 'post',                      url: '/wh/progress',                      data: {                        "count": this.count+""                      },                      dataType:'json'                    }).then(function (response) {                        if(response.data =="SUCCESS"){                            this.codeCreate = false;                            this.codeCreating = true;                            this.getProgressPercent();                        }else{                            this.$Message.error("生成失败,请检查后重新生成!");                        }                                            }.bind(this)).catch(function (error) {                      alert(error);                    });                }else{                    this.$Message.error("必须为数字!");                }            },            /*从后台拿到半分比数*/            getProgressPercent(){                setTimeout(() => {                    axios({                      method: 'get',                      url: '/wh/progress',                      dataType:'json'                    }).then(function (response) {                        if(response.data != null){                            if(response.data != "100"){                                this.percent = parseInt(response.data);                                this.getProgressPercent();                            }else{                                this.percent = parseInt(response.data);                                this.delPercentInRedis();                                this.codeCreating = false;                                this.codeDownload = true;                                this.$Message.info('生成完成');                            }                        }else {                            this.getProgressPercent();                        }                    }.bind(this)).catch(function (error) {                      alert(error);                    });                }, 1000);            },            /*txt生成后删除redis中对应的数据*/            delPercentInRedis(){                axios({                  method: 'delete',                  url: '/wh/progress',                  data: {},                  dataType:'json'                }).then(function (response) {                }.bind(this)).catch(function (error) {                  alert(error);                });            }        }    })  </script></body></html>

3.后端的配置和redis的集成(网上很多)下面是主要的代码:

Controller

import java.util.Map;import javax.annotation.Resource;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.web.bind.annotation.DeleteMapping;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.PostMapping;import org.springframework.web.bind.annotation.RequestBody;import org.springframework.web.bind.annotation.RestController;import com.wanghuan.service.ProgressService;@RestControllerpublic class CreateProgressController {    Logger log = LoggerFactory.getLogger(CreateProgressController.class);    @Resource(name = "progressService")    private ProgressService progressService;    /**     * 生成txt请求     *      * @param reqMap     * @return     */    @PostMapping(value = "/progress")    public String create(@RequestBody Map<String, Object> reqMap) {        log.info(reqMap.toString());        progressService.createTxt(Long.parseLong((String) reqMap.get("count")));        return "SUCCESS";    }    /**     * 得到进度请求     *      * @return     */    @GetMapping(value = "/progress")    public String getPercent() {        return progressService.getPercent();    }    /**     * 删除redis中数据请求     *      * @return     */    @DeleteMapping(value = "/progress")    public String delPercentInRedis() {        log.info("删除成功!");        progressService.delPercentInRedis();        return "SUCCESS";    }}

Service

public interface ProgressService {    /**     * 生成txt文本     * @param count     */    void createTxt(long count);    /**     * 得到进度     */    String getPercent();    /**     * 删除redis中的缓存     */    void delPercentInRedis();}

ServiceImpl

import java.io.BufferedWriter;import java.io.File;import java.io.FileWriter;import java.io.IOException;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.data.redis.core.StringRedisTemplate;import org.springframework.data.redis.core.ValueOperations;import org.springframework.stereotype.Service;import com.wanghuan.dao.ProgressDao;import com.wanghuan.service.ProgressService;@Service("progressService")public class ProgressServiceImpl implements ProgressService {    Logger log = LoggerFactory.getLogger(ProgressServiceImpl.class);    @Autowired    private RedisTemplate redisTemplate;    @Autowired    private StringRedisTemplate stringRedisTemplate;    @Autowired    ProgressDao progressDao;    @Override    public void createTxt(long count) {        new Thread() {            public void run() {                try {                    Thread.sleep(500);                    long startCount = 1;                    long endCount = count;                    long pcount = count / 100;                    File file = new File("target/classes/static/temp/progress.txt");                    String path = file.getAbsolutePath();                    FileWriter fw = new FileWriter(file);                    BufferedWriter bw = new BufferedWriter(fw);                    /*计数变量*/                    long currentCount = 0;                    String percent = "0";                    String percentCopy = "0";                    for (; startCount <= endCount; startCount++) {                        currentCount++;                        percentCopy = percent;                        if (count < 10000) {                            percent = String.valueOf((currentCount * 100 / count));                        } else {                            percent = String.valueOf((currentCount / (pcount)));                        }                        if ("100".equals(percent) && currentCount != count) {                            percent = "99";                        }                        if (!percentCopy.equals(percent)) {                            System.out.println(percent);                            ValueOperations<String, String> value = stringRedisTemplate.opsForValue();                            value.set("percent", percent);                        }                        String s;                        s = "WH" + currentCount;                        // 写入txt文件                        bw.append(s + "\r\n");                    }                    bw.flush();                    bw.close();                    log.info("txt文件名" + "progress.txt");                } catch (IOException e) {                    e.printStackTrace();                } catch (InterruptedException e) {                    e.printStackTrace();                }            }        }.start();    }    @Override    public String getPercent() {        String progress = "0";        ValueOperations<String, String> value = stringRedisTemplate.opsForValue();        progress = value.get("percent");        return progress;    }    @Override    public void delPercentInRedis() {        stringRedisTemplate.delete("percent");    }}
原创粉丝点击