axios文件导出显示文件导出全局提示

产品需求:

        文件导出时有时接口响应过长,想要个提示显示哪个文件正在下载中,不耽误其他的操作进行,下载完成自动清除提示。

实现效果:

        文件下载时显示全局提示显示文件携带下载时间正在下载中,下载完成清除提示,如果在下载过程中出现窗口重新刷新,刷新结束后,自动根据未下载完成的文件重新发起下载请求。

 实现过程:

1.封装api请求文件

const $axios = (opts, data, uniSign) => {
  let httpDefaultOpts = { // http默认配置
    method: opts.method,
    url: opts.url,
    responseType: opts.responseType || 'json', // 一般一个网站的responseType 都是一样的
    withCredentials: true, // 是否允许带cookie这些
    params: data,
    data: data,
    headers: {
      'Content-Type': opts.contentType || 'application/json',
      'Authorization': `Token ${getToken()}`
    },
    onDownloadProgress: opts.onDownloadProgress || null,
    cancelToken: new axios.CancelToken(function (c) {
      cancel = c // 记录当前请求的取消方法
    })
  }
  if (opts.method === 'get') {
    delete httpDefaultOpts.data
  } else if (opts.method === 'delete') {
    delete httpDefaultOpts.data
  } else {
    delete httpDefaultOpts.params
  }
  let promise = new Promise(function (resolve, reject) {
    axios(httpDefaultOpts).then(
      (res) => {
        resolve(res.data)
      }
    ).catch(
      (error) => {
        if(opts.responseType === 'blob') {
           // 用于特殊处理blob文件流形式错误
          if(store.getters.downProgress?.length > 0){
            store.getters.downProgress.forEach(gress => {
              if(gress.path === uniSign && gress.func) {
                gress.func()
              }else{
// 清空message信息
                window.$MessageDestory()
              }
            });
          }
        }else {
        }
        reject(error)
      }
    )
  })
  return promise
}

2.封装了一个公共下载的js文件

/**
 * @description 用于文件下载的接口
*/
export function downFileProgres(url, data, txt_name) {
  let uniSign = new Date().getTime() + ''
  const cur_time = dayjs().format('YYYY-MM-DD HH:mm:ss')
  const pathclose =  window.$MessageConfig(`${txt_name  + '-' + cur_time}文件正在下载中...`, 0)
  store.dispatch('setProgress', {'url': url, 'params': data, path: uniSign, 'txt_name': txt_name  + '-' + cur_time, func: pathclose})
  const service = {
    method: 'get',
    url: `/api${url}`,
    responseType: 'blob',
    onDownloadProgress: function  (progress) {
      if(Math.round(100 * progress.loaded / progress.total) === 100){
        pathclose !== undefined && pathclose()
        if(store.getters.downProgress?.length < 1) window.$MessageDestory()
      }
    }
  }
  return $axios(service, data, uniSign)
}
/**
 * @description 强制刷新浏览器重新发起下载请求
*/
export function downFileAgin(data) {
  const pathclose =  window.$MessageConfig(`${data.txt_name}文件正在下载中...`, 0)
  store.dispatch('setProgress', {'url': data.url, 'params': data.params, path: data.uniSign, 'txt_name': data.txt_name, func: data.pathclose})
  const service = {
    method: 'get',
    url: `/api${data.url}`,
    responseType: 'blob',
    onDownloadProgress: function  (progress) {
      if(Math.round(100 * progress.loaded / progress.total) === 100){
        pathclose !== undefined && pathclose()
        store.dispatch('delProgress', data.path)
        if(store.getters.downProgress?.length < 1) window.$MessageDestory()
      }
    }
  }
  return $axios(service, data.params, data.path)
}

3.封装vuex存贮文件的下载状态

const app = {
  state: () => ({
    downfile: []
  }),
  mutations: {
    SET_PROGRESS: (state, fileObj)=>{ 
      // 修改进度列表
      state.downfile.push(fileObj) 
    },
    DEL_PROGRESS: (state, props) => {
      state.downfile.splice(state.downfile.findIndex(item=>item.path == props), 1) // 删除进度列表中的进度对象
    },
    CHANGE_SETTING: (state, data) => {
      if(state.downfile.find(item=>item.path === data.path)){ 
        const cur_index = state.downfile.findIndex(item=>item.path === data.path)
        const new_obj = Object.assign({},{...data})
        state.downfile.splice(cur_index,1,new_obj)
      }
    }
  },
  actions: {
    changeSetting({ commit }, data) {
      commit('CHANGE_SETTING', data)
    },
    delProgress({commit}, data) {
      commit('DEL_PROGRESS', data)
    },
    setProgress({commit}, data) {
      commit('SET_PROGRESS', Object.assign({}, data))
    }
  }
}
export default app

4.最后在入口文件添加浏览器刷新的监听,再刷新结束后重新发起未下载完成文件的请求,请求结束后清除浏览器的缓存信息及vuex中的信息

 /**
     * @description 监听浏览器的强刷重新发起断掉的下载请求
    */
    window.addEventListener("load", () => {
      if(sessionStorage.getItem("downProgress") === null || 
        JSON.parse(window.decodeURIComponent(window.atob(sessionStorage.getItem("downProgress"))))?.length < 1) return
        const downfile = [].concat(JSON.parse(window.decodeURIComponent(window.atob(sessionStorage.getItem("downProgress")))))
        setTimeout(() => {
          sessionStorage.removeItem('downProgress') 
        },150)
        downfile.forEach(file => {
          if(file.path) {
            this.$store.dispatch('setProgress', file)
            downFileAgin(file).then(res => {
                const blob = new Blob([res], {
                  type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
              })
              if ('download' in document.createElement('a')) {
              // 非IE
                const elink = document.createElement('a')
                elink.download = file.txt_name || '数据列表'
                elink.style.display = 'none'
                elink.href = URL.createObjectURL(blob)
                document.body.appendChild(elink)
                elink.click()
                URL.revokeObjectURL(elink.href)
                document.body.removeChild(elink)
              } else {
              // IE10+
                navigator.msSaveBlob(blob, file.txt_name || '数据列表')
              }
            })
            .catch(err =>{
              file.func && file.func()
            })
            }
        
        });
    });
    /**
     * @description 浏览器强刷前把vuex的下载进程存储到session中
    */
     window.addEventListener("beforeunload", () => {
      sessionStorage.removeItem('downProgress')
      if(this.$store.getters.downProgress?.length > 0) {
        const filelist = this.$store.getters.downProgress.filter(val => val.path)
        sessionStorage.setItem('downProgress', window.btoa(window.encodeURIComponent(JSON.stringify(filelist))))
      } 
    })

你可能感兴趣的:(vue3.0x,javascript,vue.js)