vue后端传文件流转化成blob对象,前端点击下载返回undefined

效果如下
在这里插入图片描述
处理后的返回
在这里插入图片描述

<template>
  <div class="content-box">
    <div class="container">
      <div>。。。</div>
    </div>
  </div>
</template>

<script>
import {  exportProjectStandard } from '@/api/brand/standard'

export default {
  props: {},
  data() {
    return {}
  },
  methods: {
    gotoExport(row){
      // console.log(row);
      try {
        // window.location.href = `${ process.env.VUE_APP_BASE_BRAND_API }/v1/inspectionstandard/exportProject?id=${row.id}&standardName=${row.title}`
        // window.open(`${ process.env.VUE_APP_BASE_BRAND_API }/v1/inspectionstandard/exportProject?id=${row.id}&standardName=${row.title}`)
        // this.$message.success('数据导出中,请稍等')
        
        // 调接口文件流形式
        let parmas = {
          id: row.id,
          standardName: row.title
        }
        exportProjectStandard(parmas).then(res => {
          console.log(res);
          // 因为后端直接返回的就是blob数据流格式
          // if (res.code == 200) {
            const content = res;
            const blob = new Blob([content])
            const fileName = row.title + '.xls';  //自定义下载文件的名字
            if ('download' in document.createElement('a')) { // 非IE下载
              const elink = document.createElement('a');
              elink.download = fileName;
              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);
            }
          // }
        }).catch((error) => {
          this.$message.error('导出异常,请稍后重试')
        	console.log(error.response)   //可获取错误的返回信息
          if (error.response.status == 400) {}
        }).finally(() => {})
      } catch (error) {
        this.$message.error('导出失败')
      }
    }
  }
}
</script>

<style lang="scss" scoped>

</style>

如图blob文件流格式
在这里插入图片描述
封装的方法如下:

import axios from 'axios'
// import { Message } from 'element-ui'
import store from '@/store'
import { goLoginPage } from '@/utils'
import { getAccessToken, getRefreshToken, getAccessTokenTTL } from '@/utils/auth'

const SYSTEM_APPID = process.env.VUE_APP_SYSTEM_APPID
let isRefreshing = false // 是否正在刷新token
let requests = [] // 请求队列

const exculdeUrls = ['/xxx/authorize/generateToken', '/xxx/authorize/refreshToken']

function checkExculdeUrls(url) {
  let flag = false
  exculdeUrls.map(item => {
    if (url.indexOf(item) >= 0) flag = true
  })
  return flag
}

function noTokenData() {
  return !getAccessToken() || !getRefreshToken() || !getAccessTokenTTL()
}

const service = axios.create({
  baseURL: process.env.VUE_APP_BASE_BRAND_API,
  // withCredentials: true,
  timeout: 300000
})

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

    // 不需要验证token的接口
    if (checkExculdeUrls(config.url)) {
      return config
    }

    // token数据丢失
    if (noTokenData()) {
      console.log('token数据丢失');
      goLoginPage()
    }

    if (new Date().getTime() >= getAccessTokenTTL()) {
      // accessToken失效,接口放入队列,并刷新token
      if (!isRefreshing) {
        isRefreshing = true;
        const sData = {
          appID: SYSTEM_APPID,
          refreshToken: getRefreshToken(),
          timestamp: new Date().getTime(),
          version: '1.0'
        }
        store.dispatch('user/refreshToken', sData).then(res => {
          isRefreshing = false
          return res.item.accessToken
        }).then(token => {
          requests.forEach(cb => cb(token))
          requests = []
        }).catch(err => {
          isRefreshing = false
          console.error('refresh token error: ', err)
        })
      }
      const retryOriginalRequest = new Promise((resolve) => {
        requests.push((token) => {
          config.headers['Authorization'] = token
          resolve(config)
        })
      })
      return retryOriginalRequest
    } else {
      // accessToken有效
      const token = getAccessToken()
      if (token) {
        config.headers['Authorization'] = token
      }

      return config
    }
  },
  error => {
    console.log(error)
    return Promise.reject(error)
  }
)

service.interceptors.response.use(
  response => {
    return response.data
  },
  error => {
    // const errMsg = (error.response && error.response.data && error.response.data.message) || error.message
    // Message({
    //   message: errMsg,
    //   type: 'error'
    // })
    switch (error.response.data.code) {
      case 910005: // 返回910005 缺失accessToken
      case 910006: // 返回910006 获取SESSIONID失败
      case 910007: // 返回910007 accessToken过期
      case 910008: // 返回910008 找不到用户信息
      case 910009: // 返回910007 refreshToken过期
        goLoginPage()
        break
      default:
        console.log('err' + error)
    }
    return Promise.reject(error)
  }
)

//上传附件axios接口封装
const upload = {
  uploadFile(url, payload, cancelToken, cd) {
    return service({
      url: url,
      method: "post",
      data: payload,
      onUploadProgress: function(progressEvent) {
        if (cd && progressEvent.lengthComputable) {
          cd(progressEvent);
        }
      },
      cancelToken: cancelToken,
    });
  },
}
export {
  upload,
  service,
}
export default service

import request from '@/utils/request'

// 导出标准接口
export function exportProjectStandard(params){
  return  request({
    url: '/v1/inspectionstandard/exportProject',
    timeout: 60 * 60 * 60 * 1000, // 设置请求超时时间
    xhrFields: {
      withCredentials: true
    },
    method:'get',
    params,
    responseType: 'blob',
  });
}
Logo

前往低代码交流专区

更多推荐