vue文件下载

// 创建一个隐藏的 a 标签
  const a = document.createElement('a');
  a.href = url;
  // 从 URL 中提取文件名
  a.download = url.substring(url.lastIndexOf('/') + 1);
  a.style.display = 'none';
  document.body.appendChild(a);
  // 模拟点击 a 标签
  a.click();
  // 移除 a 标签
  document.body.removeChild(a);

1,拦截器request.ts中添加

// 添加响应拦截器
service.interceptors.response.use(
    (response) => {
     这里要有判断Blob
if (response.data instanceof Blob || response.data instanceof ArrayBuffer) { return response; } // 对响应数据做点什么 const res = response.data; switch (res.code) { case 200: return res; case 302: Session.set('userId', res.data || ''); ElMessageBox.alert(`用户首次登录,请修改密码后再重新登录`, '提示', { confirmButtonText: '确认', type: 'warning', }).then(() => { router.push('/resetPwdPage'); }).catch(() => { router.push('/resetPwdPage'); }); break; case 401: //清除所有缓存 _clearAllStore.clear(); location.reload(); // ElMessageBox.alert(`${res.msg},请重新登录`, '提示', { // confirmButtonText: '确认', // type: 'warning', // }).then(() => { // router.push(LOGIN_URL); // }).catch(() => { // router.push(LOGIN_URL); // }); break; case 404: ElMessage.warning("接口不存在,请检查接口地址是否正确!"); break; case 500: // ElMessage.error(res.msg); return res default: return Promise.reject(service.interceptors.response); } }, (error) => { // 对响应错误做点什么 if (error.message.indexOf('timeout') != -1) { ElMessage.error('网络超时'); } else if (error.message == 'Network Error') { ElMessage.error('网络连接错误'); } else { if (error.response.data) ElMessage.error(error.response.msg); else ElMessage.error('接口路径找不到'); } return Promise.reject(error); } );

2,然后封装downLoad.ts

export const downloadFile = (res: any, fileName:string, params?: any) => {
    // 从响应头中获取文件名
    const disposition = res.headers['content-disposition'];
    if (disposition) {
        const filenameMatch = disposition.match(/filename=(.+)/);
        if (filenameMatch && filenameMatch[1]) {
            fileName = decodeURIComponent(filenameMatch[1]);
        }
    }

    const blob = new Blob([res.data]);
    const url = window.URL.createObjectURL(blob);
    const doca = window.document.createElement('a');
    doca.href = url;
    doca.setAttribute('download', decodeURI(fileName));
    if (typeof doca.download === 'undefined') {
        doca.setAttribute('target', '_blank');
    }
    window.document.body.appendChild(doca);
    doca.click();
    window.document.body.removeChild(doca);
    window.URL.revokeObjectURL(url);
}

 3,api调用需要添加responseType

import request from '/@/utils/request';

/**
 * 有关文件上传下载的接口
 * @method getFile 获取文件
 * @method postFile 上传文件
 *  @method deleteFile 删除文件
 */
export function useFileApi() {
    return {
        getFile: (params: object) => {
            return request({
                url: '/file',
                method: 'GET',
                params,
                responseType: 'blob',
            });
        },
        postFile: (data: object) => {
            return request({
                url: '/file',
                method: 'POST',
                data,
                headers: {
                    'Content-Type': 'multipart/form-data;'
                }
            });
        },
        deleteFile: (data: object) => {
            return request({
                url: '/file',
                method: 'DELETE',
                data
            });
        }
    };
}

4,页面调用接口

//点击文件列表中已上传的文件时的钩子,参数为上传的文件
const handlePreview: UploadProps['onPreview'] = (uploadFile: any) => {
    console.log("🚀 ~ 点击文件列表中已上传的文件时的钩子:", uploadFile)
    const params = {
        id: uploadFile.id,
    }
    fileStores.getFile(params)
}

5,store里调用downLoad.ts

import { defineStore } from 'pinia';
import { useFileApi } from '/@/api/file/index';
import { ElMessage } from 'element-plus';
import { downloadFile } from '/@/utils/downloadFile';

/**
 * 日志信息
 */
export const fileStore = defineStore('fileMag', {
    state: (): any => ({
        fileData: '', // 文件信息
    }),
    getters: {
    },
    actions: {
        /**
         * 下载文件
         * @param params
         * @returns
         */
        async getFile(params: object, callback?: Function) {
            const { getFile } = useFileApi();
            const res: any = await getFile(params);
            if (res?.status === 200) {
                downloadFile(res, `下载.pdf`)
                callback && callback();
            } else {
                ElMessage({
                    message: res?.msg || '文件下载失败!',
                    type: 'error',
                })
            }
        },
        /**
         * 上传文件
         * @param data
         * @returns
         */
        async uploadFile(data: any, callback?: Function) {
            const { postFile } = useFileApi();
            const res: any = await postFile(data);
            if (res?.code === 200) {
                ElMessage({
                    message: res?.msg || '文件上传成功!',
                    type: 'success',
                })
                this.fileData = res?.data || '';
                callback && callback();
                return res;
            } else {
                ElMessage({
                    message: res?.msg || '文件上传失败!',
                    type: 'error',
                })
            }
        },
        /**
        * 删除文件
        * @param params
        * @returns
        */
        async deleteFile(data: object, callback?: Function) {
            const { deleteFile } = useFileApi();
            const res: any = await deleteFile(data);
            if (res?.code === 200) {
                ElMessage({
                    message: res?.msg || '文件删除成功!',
                    type: 'success',
                })
                callback && callback();
            } else {
                ElMessage({
                    message: res?.msg || '文件删除失败!',
                    type: 'error',
                })
            }
        }
    },
});

 

封装下载方法

import store from '@/store'
import axios from 'axios'
import {
  Notification
} from 'element-ui'
import {
  getJSONToken,
  removeToken
} from '@/utils/auth'
function handleDealDataStream(response) {
  const {
    data,
    headers
  } = response
  if (data['type'] === 'application/json') {
    //处理后端报错信息
    const reader = new FileReader();
    reader.onload = function () {
      const { message } = JSON.parse(reader.result);
      Notification.error({
        message: message,
        duration: 3000
      })
    }
    reader.readAsText(data)
  } else {
    let blob = new Blob([data], {
      type: ''
    })
    const fileName = headers['content-disposition'].split(';').slice(1).join('').split('=').splice(1).join('')
    const _fileName = decodeURIComponent(fileName)
    if (window.navigator.msSaveOrOpenBlob) {
      navigator.msSaveBlob(blob, _fileName)
    } else {
      var link = document.createElement('a')
      link.href = window.URL.createObjectURL(blob)
      link.download = _fileName
      link.click()
      //释放内存
      window.URL.revokeObjectURL(link.href)
    }
  }
}

 

export default function exportExcel ( url, options = {}, type = 'post', fileOperateType = 'download') {
  return new Promise((resolve, reject) => {
    const token = getJSONToken('token') 
    axios.defaults.headers['Authorization'] = 'Bearer ' + token 
    axios.defaults.headers['Sid'] = '234'
    axios.defaults.headers['content-type'] = 'application/json;charset=UTF-8'if(type ==="post") {
      axios({
        method: type,
        url: url, // 请求地址
        data: options, // 参数
        responseType: 'blob' // 表明返回服务器返回的数据类型zhm
      }).then(
        response => {
          resolve(response)
          if (fileOperateType === 'download') {
            handleDealDataStream(response)    
          }
        },
        err => {
          reject(err)
        }
      )
    } else {
      axios({
        method: type,
        url: url, // 请求地址
        params: options, // 参数
        responseType: 'blob' // 表明返回服务器返回的数据类型zhm
      }).then(
        response => {
          resolve(response)
          if (fileOperateType === 'download') {
            handleDealDataStream(response)    
          }      
        },
        err => {
          reject(err)  
        }
      )
    }
  })
} 

 

  

function handleDealDataStream(response) {
  const {
    data,
    headers
  } = response
  if (data['type'] === 'application/json') {
    //处理后端报错信息
    const reader = new FileReader();
    reader.onload = function () {
      const { message } = JSON.parse(reader.result);
      Notification.error({
        message: message,
        duration: 3000
      })
    }
    reader.readAsText(data)
  } else {
    let blob = new Blob([data], {
      type: ''
    })
    const fileName = headers['content-disposition'].split(';').slice(1).join('').split('=').splice(1).join('')
    const _fileName = decodeURIComponent(fileName)
    if (window.navigator.msSaveOrOpenBlob) {
      navigator.msSaveBlob(blob, _fileName)
    } else {
      var link = document.createElement('a')
      link.href = window.URL.createObjectURL(blob)
      link.download = _fileName
      link.click()
      //释放内存
      window.URL.revokeObjectURL(link.href)
    }
  }
}
// 创建一个隐藏的 a 标签
  const a = document.createElement('a');
  a.href = url;
  // 从 URL 中提取文件名
  a.download = url.substring(url.lastIndexOf('/') + 1);
  a.style.display = 'none';
  document.body.appendChild(a);
  // 模拟点击 a 标签
  a.click();
  // 移除 a 标签
  document.body.removeChild(a);
posted @ 2022-07-12 10:20  磊~~  阅读(28)  评论(0)    收藏  举报