Vue+element+springboot to implement file download progress bar display function example

Vue+element+springboot to implement file download progress bar display function example

This article mainly introduces the example of vue+element+springboot to realize the file download progress bar display function, and shares it with you. The details are as follows

Final Rendering

1. Demand Background

Recently, we received an optimization request. The original system file download function was not user-friendly, especially when downloading some time-consuming files. Users waited on the page without knowing the download progress and always thought the system was stuck.

2. Optimization plan

Optimize download speed in the background (you can study fragmented downloading, but I won’t expand on it here)
Improve the front-end user experience (for example, after clicking download, you need to display the progress to let the customer know that the download is in progress)

3. Specific implementation

Here we choose the solution in 2.2 to transform the front-end user experience. The purpose of writing this article is to record the solution process at that time, hoping to help everyone; the technical background of the solution used in this article: front-end vue + element-ui, back-end: springboot front-end and back-end separation, without further ado, directly on the code;

3.1 Front-end code

1. Define a pop-up layer (the style can be determined according to your own preferences)

<!--Download progress bar-->
    <el-dialog title="Downloading, please wait" :visible.sync="fileDown.loadDialogStatus" :close-on-click-modal="false" 
      :close-on-press-escape="false" :show-close="false" width="20%">
      <div style="text-align: center;">
        <el-progress type="circle" :percentage="fileDown.percentage"></el-progress>
      </div>
      <div slot="footer" class="dialog-footer">
        <el-button type="primary" @click="downClose">Cancel download</el-button>
      </div>  
    </el-dialog>

Define an object in data()

fileDown: {
        loadDialogStatus: false, // Pop-up box control status percentage: 0, // Progress bar percentage source: {}, // Cancel download resource object },

3. Main method (note to replace the following parameters, background address, file name, etc.)

downFile(row) {
    //Put parameters here var param = {};
    this.fileDown.loadDialogStatus = true;
    this.fileDown.percentage = 0;
    const instance = this.initInstance();
    instance({
        method: "post",
        withCredentials: true,
        url: "Replace download address",
        params: param,
        responseType: "blob"
    }).then(res => {
        this.fileDown.loadDialogStatus = false;
        console.info(res);
        const content = res.data;
        if (content.size == 0) {
          this.loadClose();
          this.$alert("Download failed");
          return ;
        }
        const blob = new Blob([content]);
        const fileName = row.fileName; //Replace the file name if ("download" in document.createElement("a")) {
          // Non-IE download const elink = document.createElement("a");
          elink.download = fileName;
          elink.style.display = "none";
          elink.href = URL.createObjectURL(blob);
          document.body.appendChild(elink);
          elink.click();
          setTimeout(function() {
            URL.revokeObjectURL(elink.href); // Release the URL object document.body.removeChild(elink);
          }, 100);
        } else {
          // IE10+ download navigator.msSaveBlob(blob, fileName);
        }
      }).catch(error => {
          this.fileDown.loadDialogStatus = false;
          console.info(error);
      });
  },
initInstance() {
      var _this = this;
      //Resource token for cancellation this.fileDown.source = axios.CancelToken.source();
      const instance = axios.create({ //The axios object should be imported in advance or replaced with your globally defined onDownloadProgress: function(ProgressEvent) {
          const load = ProgressEvent.loaded;
          const total = ProgressEvent.total;
          const progress = (load / total) * 100;
          console.log('progress='+progress);
          // Calculation has already been done at the beginning. This must exceed the previous calculation to continue if (progress > _this.fileDown.percentage) {
            _this.fileDown.percentage = Math.floor(progress);
          }
          if(progress == 100){
            //Download completed_this.fileDown.loadDialogStatus = false;
          }
        },
        cancelToken: this.fileDown.source.token, //Declare a cancel request token
      });
      return instance;
    },
    downClose() {
      //Interrupt download this.$confirm("Clicking Close will interrupt the download. Are you sure you want to close it?", this.$t("button.tip"), {
        confirmButtonText: this.$t("button.confirm"),
        cancelButtonText: this.$t("button.cancel"),
        type: "warning"
      }).then(() => {
          //Interrupt download callback this.fileDown.source.cancel('log==customer manually canceled download');
      }).catch(() => {
          //Cancel -- do nothing});      
    },

3.2 Background Code

The main purpose of the background is to return the calculated file size, otherwise the total taken when the front-end calculates the progress will always be 0, which is a hidden pit.
Key code: (There are many ways to download the complete background on the Internet, here are just the key points and points that need attention)

//Get the local file and calculate the sizeFile file = new File(zipFileName);//Read the compressed fileInputStream inputStream = new FileInputStream(file);
int totalSize = inputStream.available(); //Get the file size logger.info("After compression === current file download size size={}", totalSize);
response.setHeader("Content-Length", totalSize+""); //Note that you must set the setHeader property before response.getOutputStream(), otherwise it will not take effect OutputStream out = response.getOutputStream();
Subsequent omissions...

4. Conclusion

You may encounter another problem during use, that is, the backend takes a lot of time to calculate the file size, causing the front-end progress bar to remain motionless for a long time, and users will still feel stuck, which does not meet our needs;

My solution here is to make a timer on the front end. When you click download, the timer will run first, for example, increasing the progress by 1% in 2 seconds. When the total file size is returned by the background, when the calculated percentage (percentage) exceeds the percentage (percentage) of the timer, turn off the timer and replace the attribute (percentage) of the progress percentage. Remember, there must be an upper limit for the automatic percentage increase (percentage) of this timer.
The advantage is that when the user clicks the download button, the front end will respond. Although the previous response may be false, as long as the connection is good, it doesn’t matter whether it is true or false.

This is the end of this article about vue+element+springboot to implement a file download progress bar display function example. For more related element springboot download progress bar content, please search 123WORDPRESS.COM's previous articles or continue to browse the following related articles. I hope you will support 123WORDPRESS.COM in the future!

You may also be interested in:
  • How to implement a real-time updated progress bar in SpringBoot
  • Springboot upload function complete example with progress bar

<<:  6 Uncommon HTML Tags

>>:  Solve the problem that Docker pulls MySQL image too slowly

Recommend

Analysis of the advantages and disadvantages of MySQL stored procedures

MySQL version 5.0 began to support stored procedu...

How to implement remote automatic backup of MongoDB in Linux

Preface After reading the previous article about ...

Mysql join query principle knowledge points

Mysql join query 1. Basic concepts Connect each r...

Introduction to Semantic HTML Tags

In the past few years, DIV+CSS was very popular in...

Detailed explanation of the loading rules of the require method in node.js

Loading rules of require method Prioritize loadin...

Use of Linux ls command

1. Introduction The ls command is used to display...

How to solve the problem that Docker container has no vim command

Find the problem Today, when I tried to modify th...

How to clear mysql registry

Specific method: 1. Press [ win+r ] to open the r...

Vue routing to implement login interception

Table of contents 1. Overview 2. Routing Navigati...

A brief discussion on the font settings in web pages

Setting the font for the entire site has always b...

isPrototypeOf Function in JavaScript

Table of contents 1. isPrototypeOf() Example 1, O...

Vue3.0 project construction and usage process

Table of contents 1. Project construction 2: Dire...

IIS configuration of win server 2019 server and simple publishing of website

1. First remotely connect to the server 2. Open S...