关于element el-upload文件上传的封装

1,786 阅读1分钟

1、html标签

<template>
  <span>
<!--          :on-change="handelChange"-->
    <el-upload
      class="upload-demo"
      name="file"
      ref="upload"
      :headers="fileHeaders"
      :action="uploadApi"
      multiple
      :accept="fileType"
      :limit="limit"
      // 这里的value是双向绑定用的
      :file-list='value'
      :before-upload="handleBeforeUpload"
      :on-success="handelSuccess"
      :on-exceed="handleExceed"
      :before-remove="beforeRemove"
      :on-preview="handlePreview"
      :on-error="handelError"
      :on-remove="handelRemove">
      <el-button size="small" type="primary">点击上传</el-button>
    </el-upload>
  </span>
</template>

2、script标签的使用

<script>
  import Cookies from 'js-cookie';
  import prefix from '@/utils/config/prefix'; // 获取到接口的代理名称
  import { downFile, filePreView } from '@/utils/common';

  const baseUrl = prefix.thirdApi;
  const acceptFileTypeWhiteStr = 'xls,xlsx,doc,docx,txt,pdf,ppt,pptx,rar,zip,arj,gz,z,bmp,gif,jpg,jpeg,pic,png,tif,mp4';
  export default {
    name: 'index',
    props: {
      // 上传文件pai
      uploadApi: {
        type: String,
        default: `${baseUrl}storage/saveFile`,
      },
      exportApi: {
        type: String,
        default: `${baseUrl}storage/getFile`,
      },
      preViewApi: {
        type: String,
        default: `${baseUrl}storage/previewFile`,
      },
      // // 当前文件数组
      // currentFileList: {
      //   type: Array,
      //   default: () => [],
      // },
      // 可上传的文件数量
      limit: {
        type: Number,
        default: 5,
      },
      // 文件大小限制 单位 M
      limitFileSize: {
        type: Number,
        default: 50,
      },
      // 可接收文件上传类型
      acceptType: {
        type: String,
        default: acceptFileTypeWhiteStr,
      },
      // // 可接收文件
      value: {
        type: Array,
        default: () => [],
      },
    },
    data() {
      return {
        // 上传文件的列表
        fileType: '.xls,.xlsx,.doc,.docx,.txt,.pdf,.ppt,.pptx,.rar,.zip,.arj,.bmp,.gif,.jpg,.jpeg,.pic,.png,.tif,.mp4',
        fileHeaders: {
          Authorization: Cookies.get('accessToken'),
        },
      };
    },
    methods: {
    ## /** 上传文件之前的钩子, 可以判断类型 */
      // eslint-disable-next-line consistent-return
      handleBeforeUpload(file) {
        const fileName = file.name.substring(0, file.name.lastIndexOf('.'));
        const reg = /([*"'<>/])+/;
        if (this.acceptType) {
          const fileType = file.name.substring(file.name.lastIndexOf('.') + 1);
          const acceptArr = this.acceptType.split(',');
          const valid = acceptArr.join('、');
          if (acceptArr.indexOf(fileType.toLowerCase()) === -1) {
            this.$message({
              message: `上传文件只能是${valid} 格式!`,
              type: 'warning',
            });
            return false;
          }
        }
        if (reg.test(fileName) || fileName.indexOf(' ') === 0 || (fileName.lastIndexOf(' ') === fileName.length - 1)) {
          this.$message.error('文件名称不符合规范!');
          return false;
        }
        if (this.limitFileSize) {
          const { size } = file;
          let limitSize = this.limitFileSize * 1024 * 1024;
          if (file.type.indexOf('mp4') !== -1) {
            limitSize = 200 * 1024 * 1024;
          }
          if (size > limitSize) {
            this.$message({
              message: `文件大小限制${this.limitFileSize}M以内,当前文件大小${Math.round((size / 1024 / 1024) * 100) / 100}M!`,
              type: 'warning',
            });
            return false;
          }
        }
      },
    ## /** 上传成功之后的钩子 */
      handelSuccess(response, file, fileList) {
        if (response.code === 200) {
          this.$message.success('上传成功');
          // 双向绑定的发出去的事件
          this.$emit('input', fileList);
          // this.$emit('fileSuccessUpload', response, file, fileList);
        } else {
          // 文件上传失败删除页面上显示出来的文件
          const delFileName = file.name;
          // 方式二
          let selectFiles = this.$refs.upload.$children[1].files;
          selectFiles.some((v, idx) => {
            const flag = v.name === delFileName;
            if (flag) {
              selectFiles = selectFiles.splice(idx, 1);
            }
            return flag;
          });
          this.$message.error('上传失败');
        }
      },
    ## /** 上传文件失败的钩子 */
      handelError(err, file, fileList) {
        this.$message.error(`${err}`);
      },
    ## /** 删除文件之前钩子 */
      beforeRemove(file, fileList, type = 'confirm') {
        if (file && file.status === 'success' && type === 'confirm') {
          return new Promise((resolve, reject) => {
            this.$confirm('确定删除?', '提示', {
              confirmButtonText: '确定',
              cancelButtonText: '取消',
              type: 'warning',
            }).then(() => {
                resolve(true);
              }).catch(() => {
                // this.$message({
                //   type: 'info',
                //   message: '已取消',
                // });
              // eslint-disable-next-line prefer-promise-reject-errors
                reject(false);
              });
          });
        }
        return true;
      },
    ## /** 删除成功后的数据 */
      handelRemove(file, fileList) {
        this.$emit('input', fileList);
      },
    ## /** 判断文件上传数量的钩子 */
      handleExceed(files, fileList) {
        this.$message.warning(
          `当前限制选择 ${this.limit} 个文件,本次选择了 ${files.length} 个文件,共选择了 ${files.length
          + fileList.length} 个文件`,
        );
      },
      // /** 上传文件不管成功还是失败都会触发 */
      // handelChange(file, fileList) {
      //   if (file.status === 'success') {
      //     this.$emit('input', fileList);
      //   }
      // },
    ## /** 点击文件发生的事件 */
      handlePreview(file) {
        this.$confirm('请选择您所需要的操作?', '提示', {
          confirmButtonText: '下载',
          cancelButtonText: '预览',
          distinguishCancelAndClose: true,
          closeOnClickModal: false,
          type: 'warning',
        }).then(() => {
          if (file && file.status === 'success') {
            let params;
            if (file.response && file.response.content) {
              params = { id: file.response.content };
            } else {
              params = { id: file.filePath };
            }
            downFile(this.exportApi, params, file, 'get');
          }
        }).catch((action) => {
          if (action === 'cancel') {
            const fileList = 'xls,xlsx,doc,docx,txt,pdf,ppt,pptx,gif,jpg,jpeg,pic,png,';
            if (file && file.status === 'success') {
              const fileType = file.name.substring(file.name.lastIndexOf('.') + 1);
              if (fileList.indexOf(fileType) > -1) {
                const params = {
                  id: file?.response?.content || file.filePath,
                };
                filePreView(this.preViewApi, params);
              } else {
                this.$message.warning(`当前仅支持${fileList}文件预览`);
              }
            }
          }
        });
      },
    },
  };
</script>

3、文件预览下载的公共方法

/** zzfy文件下载 */
const downFilejx = (res:any, file:any) => {
  // const content = res.data;
  // const blob = new Blob([content]); // 构造一个blob对象来处理数据
  // const fileName = file.name; // 导出文件名
  const blob = new Blob([res.data], { type: 'application/actet-stream;charset=utf-8' });

  const contentDisposition = res.headers['content-disposition']; // 从response的headers中获取filename, 后端response.setHeader("Content-disposition", "attachment; filename=xxxx.docx") 设置的文件名;
  const patt = new RegExp('filename=([^;]+\.[^\.;]+);*');
  const result = patt.exec(contentDisposition);
  // @ts-ignore
  const filename = common.toDecodeURIComponent(result[1]);
  // for IE
  if (window.navigator && window.navigator.msSaveOrOpenBlob) {
    window.navigator.msSaveOrOpenBlob(blob, filename);
  } else {
    const downloadElement = document.createElement('a');
    const href = window.URL.createObjectURL(blob); // 创建下载的链接
    downloadElement.style.display = 'none';
    downloadElement.href = href;
    downloadElement.download = filename; // 下载后文件名
    document.body.appendChild(downloadElement);
    downloadElement.click(); // 点击下载
    document.body.removeChild(downloadElement); // 下载完成移除元素
    window.URL.revokeObjectURL(href); // 释放掉blob对象
  }
};
export function downFile(url:any, params:any, file:any, type:any) {
  if (type === 'post') {
    outHttpClient.post(url, params, { responseType: 'blob' }).then((res) => {
      downFilejx(res, file);
    });
  }
  if (type === 'get') {
    outHttpClient.get(url, {
      params,
      responseType: 'blob',
    }).then((res) => {
      downFilejx(res, file);
    });
  }
}

/**
 * 文件预览
 * @author: zzfy
 * @api  预览的结构地址
 * @params  预览的参数
 */
export function filePreView(api: string, params: any) {
  outHttpClient.get(api, {
    params,
  }).then((res:any) => {
    /** 第三种 模拟用户点击,新窗口打开 */
    const aEle = document.createElement('a');
    aEle.setAttribute('href', res);
    aEle.setAttribute('target', '_blank');
    aEle.setAttribute('id', 'previewJumpEle');
    // 防止重复添加
    if (!document.getElementById('previewJumpEle')) {
      document.body.appendChild(aEle);
    }
    aEle.click();
    // @ts-ignore
    // eslint-disable-next-line no-unused-expressions
    (aEle.remove && aEle.remove()) || (aEle.removeNode && aEle.removeNode(true));
  }).catch((err) => {
    Message.error(`${err}`);
  });
}