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

注:

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;

@RestController
public 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");
    }
}
  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值