vue3实现下载文件流

1.在封装的axios请求中封装方法一共接受4个参数,url为请求路径,data为参数,fileName为下载的文件名称,config为请求的其余配置如timeout,baseURL等,注意第三个参数接受json格式

2.上代码:

import axios from 'axios'

import JSONbig from 'json-bigint'

import cache from '@/plugins/cache'

import { saveAs } from 'file-saver'

import { getToken } from '@/utils/auth'

import errorCode from '@/utils/errorCode'

import useUserStore from '@/store/modules/user'

import { tansParams, blobValidate ,setTimes} from '@/utils/ruoyi'

import { ElNotification , ElMessageBox, ElMessage, ElLoading } from 'element-plus'

let downloadLoadingInstance;

// 是否显示重新登录

export let isRelogin = { show: false };

axios.defaults.headers['Content-Type'] = 'application/json;charset=UTF-8'

let baseURL = ""

if(process.env.NODE_ENV === "development"){

  baseURL="/native"

  // baseURL="http://192.168.9.61:8765/api"

}else{

  baseURL = "/api/"

  // baseURL = "http://saas.test.com/api/"

}

// 创建axios实例

const service = axios.create({

  // axios中请求配置有baseURL选项,表示请求URL公共部分

  // baseURL: import.meta.env.VITE_APP_BASE_API,

  baseURL,

  // 超时

  timeout: 20000,

  // // 处理精度丢失id

  transformResponse: [function (data) {

    // Do whatever you want to transform the data

    return JSONbig.parse(data)

  }],

})

// request拦截器

service.interceptors.request.use(config => {

  let confogDataTime = config.data?config.data:config.params

  if(confogDataTime&&confogDataTime.endDateValue){

    confogDataTime.endDateValue =setTimes(confogDataTime.endDateValue)

  }

  // 是否需要设置 token

  const isToken = (config.headers || {}).isToken === false

  // 是否需要防止数据重复提交

  const isRepeatSubmit = (config.headers || {}).repeatSubmit === false

  if (getToken() && !isToken) {

    config.headers['Authorization'] = getToken() // 让每个请求携带自定义token 请根据实际情况自行修改

  }

  // get请求映射params参数

  if (config.method === 'get' && config.params) {

    let url = config.url + '?' + tansParams(config.params);

    url = url.slice(0, -1);

    config.params = {};

    config.url = url;

  }

  if (!isRepeatSubmit && (config.method === 'post' || config.method === 'put')) {

    const requestObj = {

      url: config.url,

      data: typeof config.data === 'object' ? JSON.stringify(config.data) : config.data,

      time: new Date().getTime()

    }

    const requestSize = Object.keys(JSON.stringify(requestObj)).length; // 请求数据大小

    const limitSize = 5 * 1024 * 1024; // 限制存放数据5M

    if (requestSize >= limitSize) {

      console.warn(`[${config.url}]: ` + '请求数据大小超出允许的5M限制,无法进行防重复提交验证。')

      return config;

    }

  }

  return config

}, error => {

    Promise.reject(error)

})

// 响应拦截器

service.interceptors.response.use(res => {

    // 未设置状态码则默认成功状态

    const code = res.data.code || 200;

    // 获取错误信息

    const msg = errorCode[code] || res.data.msg || errorCode['default']

    // 二进制数据则直接返回

    if (res.request.responseType ===  'blob' || res.request.responseType ===  'arraybuffer') {

      return res.data

    }

    if (res.data.status === 40101) {

      if (!isRelogin.show) {

        isRelogin.show = true;

        ElMessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', { confirmButtonText: '重新登录', cancelButtonText: '取消', type: 'warning' }).then(() => {

          isRelogin.show = false;

          useUserStore().logOut().then(() => {

            location.href = '/index';

          })

      }).catch(() => {

        isRelogin.show = false;

      });

    }

      return Promise.reject('无效的会话,或者会话已过期,请重新登录。')

    } else if (code === 500) {

      ElMessage({ message: msg, type: 'error' })

      return Promise.reject(new Error(msg))

    } else if (code === 601) {

      ElMessage({ message: msg, type: 'warning' })

      return Promise.reject(new Error(msg))

    } else if (code !== 200) {

      ElNotification.error({ title: msg })

      return Promise.reject('error')

    } else {

      return  Promise.resolve(res.data)

    }

  },

  error => {

    let { message } = error;

    if (message == "Network Error") {

      message = "后端接口连接异常";

    } else if (message.includes("timeout")) {

      message = "系统接口请求超时";

    } else if (message.includes("Request failed with status code")) {

      message = "系统接口" + message.substr(message.length - 3) + "异常";

    }

    ElMessage({ message: message, type: 'error', duration: 5 * 1000 })

    return Promise.reject(error)

  }

)

// 通用下载方法

// url:接口地址,params:下载接口的参数对象,filename:保存的文件名,config:传递给axios请求的其他配置项

export function download(url, params, filename, config) {

  downloadLoadingInstance = ElLoading.service({ text: "正在下载数据,请稍候", background: "rgba(0, 0, 0, 0.7)", })

  return service.post(url, params, {

    transformRequest: [(params) => { return tansParams(params) }],

    headers: { 'Content-Type': 'application/json;charset=UTF-8' },

    responseType: 'blob',

    ...config

  }).then(async (data) => {

    console.log(data,'then');

    const isBlob = blobValidate(data);

    if (isBlob) {

      const blob = new Blob([data])

      saveAs(blob, filename)

    } else {

      const resText = await data.text();

      const rspObj = JSON.parse(resText);

      const errMsg = errorCode[rspObj.code] || rspObj.msg || errorCode['default']

      ElMessage.error(errMsg);

    }

    downloadLoadingInstance.close();

  }).catch((r) => {

    ElMessage.error('下载文件出现错误')

    downloadLoadingInstance.close();

  })

}

export default service

3.

if (res.request.responseType ===  'blob' || res.request.responseType ===  'arraybuffer') {

      return res.data

    }为必要条件,页面使用提供两种方法

1.在main中引入import { download} from '@/utils/https',然后采用app.config.globalProperties.download= download进行全局挂载,页面中直接使用:

const exportRoder =()=>{

  let url ='';

  let fileName = '列表.xlsx';

  download(url,obj.value,fileName,{timeout:180000})

}

2.页面引入import {download} from '@/utils/http'然后使用:

const exportRoder =()=>{

  let url ='';

  let fileName = '列表.xlsx';

  download(url,obj.value,fileName,{timeout:180000})

}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值