Vue文件下载进度条的实现过程

目录
  • 需求场景:
  • 实现原理:
  • 优化过程:
    • 下载方法的组件引入mixin
    • Vuex配置进度条
  • 最终效果图
  • 参考文章:

需求场景:

1、大文件压缩过后依旧很大,接口返回response速度过慢,页面没有任何显示,体验太差。

2、需要在浏览器显示正在加载中的状态优化显示,提高用户体验

实现原理:

1、使用onDownloadProgress方法API获取进度及文件大小等数据

2、mixin混入实现监听进度条进度

3、vuex修改进度条进度

优化过程:

使用onDownloadProgress封装一个下载文件的方法

downFileProgress: function (url, params, headers, blenderApiUrl, callback, uniSign) {
   return axios({
     url: url,
     params: params,
     method: 'get',
     responseType: 'blob',
     baseURL: blenderApiUrl,
     headers: headers,
     onDownloadProgress (progress) {
       callback(progress, uniSign)
     }
   })
 }

在下载文件的地方,使用封装的方法downFileProgress

downOrgFile (row) {
  let uniSign = `${new Date().getTime()} ` // 可能会连续点击下载多个文件,这里用时间戳来区分每一次下载的文件
  const url = `${this.$api.LifeInsuranceScenario2DownFile}/${row.account_name}/${row.task_id}`
  const baseUrl = this.iframeData.blenderApiUrl
  this.$http.downFileProgress(url, {}, this.headers, baseUrl, this.callBackProgress, uniSign).then(res => {
    if (!res) {
      this.$sweetAlert.errorWithTimer('文件下载失败!')
      return
    }
    if (typeof window.navigator.msSaveBlob !== 'undefined') {
      window.navigator.msSaveBlob(new Blob([res.data]), '中间项下载.zip')
    } else {
      let url = window.URL.createObjectURL(new Blob([res.data]))
      let link = document.createElement('a')
      link.style.display = 'none'
      link.href = url
      link.setAttribute('download', 'xxx.zip')
      document.body.appendChild(link)
      link.click()
      link.remove()
    }
  })
},
callBackProgress (progress, uniSign) {
  let total = progress.srcElement.getResponseHeader('Real-Content-Length')
  // progress对象中的loaded表示已经下载的数量,total表示总数量,这里计算出百分比
  let downProgress = Math.floor((progress.loaded / total) * 100)
  // 将此次下载的文件名和下载进度组成对象再用vuex状态管理
  this.$store.commit('SET_PROGRESS', { path: uniSign, progress: downProgress })
}

创建component同等级mixin文件夹,文件夹创建index.js

import { mapState } from 'vuex'
export const mixins = {
  computed: {
    ...mapState({
      progressList: state => state.progressList
    })
  },
  data () {
    return {
      notify: {} // 用来维护下载文件进度弹框对象
    }
  },
  watch: {
    // 监听进度列表
    progressList: {
      handler (n) {
        let data = JSON.parse(JSON.stringify(n))
        data.forEach(item => {
          const domList = [...document.getElementsByClassName(item.path)]
          if (domList.find(i => i.className === item.path)) {
            // 如果页面已经有该进度对象的弹框,则更新它的进度progress
            if (item.progress) domList.find(i => i.className === item.path).innerHTML = item.progress + '%'
            if (item.progress === null) {
              // 此处容错处理,如果后端传输文件流报错,删除当前进度对象
              this.$store.commit('DEL_PROGRESS', item.path)
              this.$notify.error({ title: '错误', message: '文件下载失败!' })
            }
          } else {
            // 如果页面中没有该进度对象所对应的弹框,页面新建弹框,并在notify中加入该弹框对象,属性名为该进度对象的path(上文可知path是唯一的),属性值为$notify(element ui中的通知组件)弹框对象
            this.notify[item.path] = this.$notify.success({
              dangerouslyUseHTMLString: true,
              customClass: 'progress-notify',
              message: `<p style="width: 150px;line-height: 13px;">中间项正在下载<span class="${item.path}" style="float: right">${item.progress}%</span></p>`, // 显示下载百分比,类名为进度对象的path(便于后面更新进度百分比)
              showClose: true,
              duration: 0
            })
          }
          if (item.progress === 100) {
            // 如果下载进度到了100%,关闭该弹框,并删除notify中维护的弹框对象
            // this.notify[item.path].close()
            // 上面的close()事件是异步的,直接delete this.notify[item.path]会报错,利用setTimeout,将该操作加入异步队列
            setTimeout(() => {
              delete this.notify[item.path]
            }, 1000)
            this.$store.commit('DEL_PROGRESS', item.path) // 删除caseInformation中state的progressList中的进度对象
          }
        })
      },
      deep: true
    }
  }
}

下载方法的组件引入mixin

import { mixins } from '../mixin/index'
export default {
  mixins: [mixins],
  ......
}

Vuex配置进度条

const state = {
  progressList: []
}
export default state
const mutations = {
  SET_PROGRESS: (state, progressObj) => {
    // 修改进度列表
    if (state.progressList.length) {
      // 如果进度列表存在
      if (state.progressList.find(item => item.path === progressObj.path)) {
        // 前面说的path时间戳是唯一存在的,所以如果在进度列表中找到当前的进度对象
        state.progressList.find(item => item.path === progressObj.path).progress = progressObj.progress
        // 改变当前进度对象的progress
      }
    } else {
      // 当前进度列表为空,没有下载任务,直接将该进度对象添加到进度数组内
      state.progressList.push(progressObj)
    }
  },
  DEL_PROGRESS: (state, props) => {
    state.progressList.splice(state.progressList.findIndex(item => item.path === props), 1) // 删除进度列表中的进度对象
  },
  CHANGE_SETTING: (state, { key, value }) => {
    // eslint-disable-next-line no-prototype-builtins
    if (state.hasOwnProperty(key)) {
      state[key] = value
    }
  }
}

export default mutations
export const getProgressList = state => state.progressList
export const changeSetting = function ({ commit }, data) {
  commit('CHANGE_SETTING', data)
}
export const setprogress = function ({ commit }, data) {
  commit('SET_PROGRESS', data)
}
export const delprogress = function ({ commit }, data) {
  commit('DEL_PROGRESS', data)
}

最终效果图

参考文章:

juejin.cn/post/702437…

到此这篇关于Vue文件下载进度条的实现过程的文章就介绍到这了,更多相关Vue下载进度条内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • vue+element+springboot实现文件下载进度条展现功能示例

    目录 1. 需求背景 2. 优化方案 3. 具体实现 3.1 前端代码 3.2 后台代码 4. 总结 本文主要介绍了vue+element+springboot实现文件下载进度条展现功能示例,分享给大家,具体如下 最终效果图 1. 需求背景 最近接到一个优化需求,原系统文件下载功能体验不友好,特别是下载一些比较耗时的文件,用户在页面上傻等不知道下载的进度是怎么样的,总以为是系统卡死了. 2. 优化方案 后台优化下载速度(可以研究一下分片下载,这里不做展开) 改造前端用户体验(比如点击下载后你要显

  • vue项目实现文件下载进度条功能

    平时业务中下载文件方式常见的有俩种: 第一种,直接访问服务器的文件地址,自动下载文件: 第二种 ,服务器返回blob文件流,再对文件流进行处理和下载. 一般小文件适用于第一种下载方案,不占用过多服务器资源,而对于体积庞大的文件,常常使用文件流的方式进行传输,如图: 文件流传输成功后通过代码可以立即发起浏览器下载该文件流: 这种方式也有弊端,在文件流传输过程中,用户无法感知文件流的传输状态(进度),会造成一些困扰(无法确定当前下载操作是否已经生效).针对这种情况,我们可以在页面显示文件流的状态和传

  • Vue文件下载进度条的实现过程

    目录 需求场景: 实现原理: 优化过程: 下载方法的组件引入mixin Vuex配置进度条 最终效果图 参考文章: 需求场景: 1.大文件压缩过后依旧很大,接口返回response速度过慢,页面没有任何显示,体验太差. 2.需要在浏览器显示正在加载中的状态优化显示,提高用户体验 实现原理: 1.使用onDownloadProgress方法API获取进度及文件大小等数据 2.mixin混入实现监听进度条进度 3.vuex修改进度条进度 优化过程: 使用onDownloadProgress封装一个下

  • vue Nprogress进度条功能实现常见问题

    NProgress是页面跳转是出现在浏览器顶部的进度条 官网:http://ricostacruz.com/nprogress/ github:https://github.com/rstacruz/nprogress 下图中的这种顶部进度条是非常常见的,在vue项目中有对应的插件.Nprogress Nprogress进度条的使用方法如下: 1.安装nprogress插件 npm install --save nprogress 注意此处的--save等同于-s,就是将插件的名称及版本号保存到

  • Python展示文件下载进度条

    目录 1.前言 2.requests 3.思考 1.前言 大家在用Python写一些小程序的时候,经常都会用到文件下载,对于一些较小的文件,大家可能不太在乎文件的下载进度,因为一会就下载完毕了. 但是当文件较大,比如下载chromedriver的时候,我们如果能够看到下载的进度条,那该多么友好.毕竟在npm,pip安装包的时候都有类似的进度条. 那笔者今天就给大家分享一个展示文件下载进度条的方法. 2.requests requests库相信大家都用过,做接口测试少不了它.其实我们平时下载文件,

  • vue歌曲进度条示例代码

    注意这个不是vue-cli创建的项目 是一个引用vue.js写的html文件 ,直接粘到一个html文件就能用了,我的音乐链接隔一段时间会失效,需要自己准备音乐 有拖动和点击切换播放进度的功能 demo图片 代码 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible

  • 利用Python展示文件下载进度条

    目录 1.前言 2.requests 3.思考 1.前言 大家在用Python写一些小程序的时候,经常都会用到文件下载,对于一些较小的文件,大家可能不太在乎文件的下载进度,因为一会就下载完毕了. 但是当文件较大,比如下载chromedriver的时候,我们如果能够看到下载的进度条,那该多么友好.毕竟在npm,pip安装包的时候都有类似的进度条. 那笔者今天就给大家分享一个展示文件下载进度条的方法. 2.requests requests库相信大家都用过,做接口测试少不了它.其实我们平时下载文件,

  • Android文件下载进度条的实现代码

    main.xml: 复制代码 代码如下: <?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:orientation="vertical"    android:layout_width="fill_paren

  • Vue实现进度条变化效果

    本篇文章用Vue简单实现进度条的变化,供大家参考,具体内容如下 先上一波效果图: 点击减后,每次减百分之十 减到百分之0后,减操作按钮隐藏 然后点击重头开始,恢复到初始状态 二话不说,上代码 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>首页</title> <link rel="sty

  • vue环形进度条组件实例应用

    在做项目的时候,最好只使用一套组件库,但是很多时候我们的组件库里面没有我们需要的组件,这个时候我们还是需要自己写组件了,vux里面就没有环形进度条组件,所以需要自己写一个. 查找资料后发现了一个很好的实现方式,通过svg来实现,以前的时候学过一点svg但是没有怎么深入了解过...现在看来真是罪过,给出参考链接 https://segmentfault.com/a/1190000008149403 可以看出原作者使用了两种方式,我们选择了第二种,简单,而且好扩展.可以看到svg就想是canvas一

随机推荐