vue通过接口下载文件的封装及使用

vue通过接口下载文件的封装及使用

  • 1、先封装axios请求(request.js)
  • 2、在针对接口返回的数据流进行2次封装(http.js)
  • 3、api接口文件(material.js)
  • 4、在界面中使用

1、先封装axios请求(request.js)

import axios from 'axios'
import { Message, Loading } from 'element-ui'
import Vue from 'vue'
axios.defaults.withCredentials = true
let loading = null // 定义loading变量
const startLoading = () => {
  loading = Loading.service({
    lock: true,
    text: '正在玩命加载中……',
    background: 'rgba(0, 0, 0, 0.7)'
  })
}
// 结束 取消loading加载
const endLoading = () => {
  loading.close()
}

let needLoadingRequestCount = 0 // 声明一个变量

const showFullScreenLoading = () => {
  if (needLoadingRequestCount === 0) { // 当等于0时证明第一次请求 这时开启loading
    startLoading()
  }
  needLoadingRequestCount++ // 全局变量值++
}

const tryHideFullScreenLoading = () => {
  if (needLoadingRequestCount <= 0) return // 小于等于0 证明没有开启loading 此时return
  needLoadingRequestCount-- // 正常响应后 全局变量 --
  if (needLoadingRequestCount === 0) { // 等于0 时证明全部加载完毕 此时结束loading 加载
    endLoading()
  }
}

// import store from '../store'
Vue.prototype.$message = Message
const service = axios.create({
  // timeout: 50000, // request timeout
  baseURL: process.env.VUE_APP_BASE_API,
  withCredentials: true,
  crossDomain: true
})
// request interceptor
service.interceptors.request.use(
  config => {
    config.headers.Authorization = window.localStorage.getItem('token')
    config.headers.platform = window.sessionStorage.getItem('platform')
    showFullScreenLoading()
    return config
  },
  error => {
    Promise.reject(error)
  }
)
service.interceptors.response.use(
  response => {
    const res = response.data
    if (res.code) {
      if (res.code == 1000) {
        tryHideFullScreenLoading()
        return Promise.resolve(res)
      } else if (res.code == 1002) {
        window.sessionStorage.clear()
        Vue.prototype.$message('请登录')
        tryHideFullScreenLoading()
        return Promise.reject(res)
      } else {
        Vue.prototype.$message.warning(res.msg)
        tryHideFullScreenLoading()
        return Promise.reject(res)
      }
    } else {
      tryHideFullScreenLoading()
      return Promise.resolve(response)
    }
  }, error => {
    tryHideFullScreenLoading()
    Vue.prototype.$message(error + '请求超时')
  })

export default service

2、在针对接口返回的数据流进行2次封装(http.js)

import request from '../utils/request'
import Vue from 'vue'
const fileExport = (url, fileName, params) => {
  return request.post(url, params, {
    responseType: 'blob',
    isBlobRequest: true
  }).then(res => {
    // console.log(res, 'res')
    // 设置responseType: 'blob',导致返回数据是Blob类型数据,需要转回JSON格式,展示接口请求失败返回的msg信息
    // 创建一个 FileReader 对象
    const reader = new FileReader()
    // 设置当读取完成时的回调函数
    reader.onload = function (event) {
      try {
        // 尝试解析 JSON 数据
        const jsonData = JSON.parse(event.target.result)
        Vue.prototype.$message.warning(jsonData.msg)
        // console.log('JSON 数据解析成功:', jsonData)
        // 此处可以进行成功后的操作
      } catch (error) {
        const blob = new Blob([res.data])
        if ('download' in document.createElement('a')) { // 非IE下载
          const elink = document.createElement('a')
          const fileNameEdit = fileName || res.headers['content-disposition']
          const extractedFileName = fileNameEdit.match(/filename="([^"]+)"/)[1]
          elink.download = extractedFileName
          elink.style.display = 'none'
          elink.href = URL.createObjectURL(blob)
          document.body.appendChild(elink)
          elink.click()
          URL.revokeObjectURL(elink.href) // 释放URL 对象
          document.body.removeChild(elink)
        } else { // IE10+下载
          navigator.msSaveBlob(blob, fileName)
        }
        // console.log('JSON 数据解析失败:', error)
        // 此处可以进行解析失败后的操作
      }
    }
    // 开始读取 Blob 数据
    reader.readAsText(res.data)
  }).catch(e => {
    console.error(e)
  })
}

export { fileExport }

3、api接口文件(material.js)

import { fileExport } from '../utils/http'
// 资料包打包下载
export const materialCompress = (fileName, params) => {
  fileExport('/material/compress', fileName, params)
}

4、在界面中使用

<template>
	<div>
	...
	<div class="packageDownload">
      <van-button type="info" size="large" @click="packageDownload">打包下载</van-button>
    </div>
	</div>
</template>

<script>
import {materialCompress} from '../api/material'
export default {
	...
	methods: {
	    packageDownload () {
	      let name = '文件名称'+'.文件格式'
	      materialCompress(name, {
	        material_id: this.material_id
	      })
	    }
	}
}
</script>

你可能感兴趣的:(vue.js,javascript,前端)