文件下载方法

230 阅读2分钟

@TOC

一、普通的下载方式

import { ElNotification , ElMessageBox, ElMessage, ElLoading } from 'element-plus'
import axios from 'axios'
let downloadLoadingInstance;
//创建axios实例
const service = axios.create({
  // axios中请求配置有baseURL选项,表示请求URL公共部分
  baseURL: import.meta.env.VITE_APP_BASE_API,
  // 超时
  timeout: 10000
})

//tansParams方法
export function tansParams(params) {
  let result = ''
  for (const propName of Object.keys(params)) {
    const value = params[propName];
    var part = encodeURIComponent(propName) + "=";
    if (value !== null && typeof (value) !== "undefined") {
      if (typeof value === 'object') {
        for (const key of Object.keys(value)) {
          if (value[key] !== null && typeof (value[key]) !== 'undefined') {
            let params = propName + '[' + key + ']';
            var subPart = encodeURIComponent(params) + "=";
            result += subPart + encodeURIComponent(value[key]) + "&";
          }
        }
      } else {
        result += part + encodeURIComponent(value) + "&";
      }
    }
  }
  return result
}
// blobValidate方法啊--> 验证是否为blob格式
export async function blobValidate(data) {
  try {
    const text = await data.text();
    JSON.parse(text);
    return false;
  } catch (error) {
    return true;
  }
}

// 通用下载方法
export function download(url, params, filename) {
  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/x-www-form-urlencoded' },
    responseType: 'blob'
  }).then(async (data) => {
    const isLogin = await blobValidate(data);
    if (isLogin) {
      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) => {
    console.error(r)
    ElMessage.error('下载文件出现错误,请联系管理员!')
    downloadLoadingInstance.close();
  })
}

二、下载压缩包zip文件方法

后端返回多个数据打包的一个zip形式的二进制数据流,前端接收之后点击下载一个zip压缩包,里面包含多个文件.

// 封装axios的下载数据流转换成zip
export function downLoadFileZip (url, params = {}, fileName, baseURL, timeout) {
  if (baseURL) {
    axios.defaults.baseURL = baseURL
  }
  if (timeout) {
    axios.defaults.timeout = timeout
  }

  let config = {
    'responseType': 'blob',
    'Access-Control-Allow-Origin': '*',
    'Content-Type': 'application/octet-stream; charset=utf-8',
    headers:{
      Authorization:'Bearer ' + getToken()
    }
  }
  axios.post(url, params, config).then(response => {
    fileName = getFileName(fileName, response)
    // 二进制类型的大对象, type对应文档类型
    let blob = new Blob([response.data], { type: 'application/zip' })
    if ('download' in document.createElement('a')) {
      const elink = document.createElement('a') // 创建a标签
      elink.download = fileName // 重命名文件
      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, fileName)
    }
  })
      .catch(error => {
        console.log(error)
      })
}

/**
 * 获取文件面那改成
 * @param {*} fileName 文件名称
 * @param {*} response 响应
 */
function getFileName(fileName, response){
  // 需要响应设置此header暴露给外部,才能获取到
  let contentDisposition = response.headers['content-disposition']
  if (contentDisposition) {
    // 正则获取filename的值
    let filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/
    let matches = filenameRegex.exec(contentDisposition)
    if (matches != null && matches[1]){
      fileName = matches[1].replace(/['"]/g, '')
    }
    // 通过 URLEncoder.encode(pFileName, StandardCharsets.UTF_8.name()) 加密编码的, 使用decodeURI(fileName) 解密
    fileName = decodeURI(fileName)
    // 通过 new String(pFileName.getBytes(), StandardCharsets.ISO_8859_1) 加密编码的, 使用decodeURI(escape(fileName)) 解密
    // fileName = decodeURI(escape(fileName))
  }
  return fileName
}

三、点击按钮下载文件

后端返回数据流,前端接收数据流,处理成excel文件下载

	//页面布局
	<el-button type="primary" plain icon="Download" @click="handleDownload($event)">下载模板</el-button>
	//js逻辑处理
    function handleDownload(e){
          e.stopPropagation();
          //downloadTem:是返回文件数据流接口
          downloadTem().then((res) => {
            const link = document.createElement("a");
            //接收数据流,数据可能是res 也可能是res.data,type表示接收的格式类型
            let blob = new Blob([res], {type: "application/vnd.ms-excel"});
            link.style.display = "none";
            link.href = URL.createObjectURL(blob);
            link.download = '模板下载.xlsx';
            document.body.appendChild(link);
            link.click();
          })
    }