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

How to start jar package and run it in the background in Linux

The Linux command to run the jar package is as fo...

How to install FastDFS in Docker

Pull the image docker pull season/fastdfs:1.2 Sta...

WeChat applet implements waterfall flow paging scrolling loading

This article shares the specific code for WeChat ...

Vue sample code for easily implementing virtual scrolling

Table of contents Preface Rolling principle accom...

How to use physics engine joints in CocosCreator

Table of contents mousejoint mouse joint distance...

Tutorial on deploying nginx+uwsgi in Django project under Centos8

1. Virtual environment virtualenv installation 1....

Linux uses iftop to monitor network card traffic in real time

Linux uses iftop to monitor the traffic of the ne...

Detailed explanation of CocosCreator message distribution mechanism

Overview This article begins to introduce content...

Detailed explanation of the usage of MySQL data type DECIMAL

MySQL DECIMAL data type is used to store exact nu...

How to use less in WeChat applet (optimal method)

Preface I am used to writing less/sass, but now I...

How to use stored procedures in MySQL to quickly generate 1 million records

Preface When testing, in order to test the projec...

RHEL7.5 mysql 8.0.11 installation tutorial

This article records the installation tutorial of...

JavaScript uses setTimeout to achieve countdown effect

In order to enhance the ability to write JavaScri...