el-upload 文件上传、图片视频预览、word下载

2,963 阅读1分钟

需求:选择文件后不自动上传,先预览,也可下载,最后和表单其他参数一起保存提交调接口。

//上传组件
<el-upload
	ref="upload"
    action="#"
    :on-remove="handleRemove"
    :http-request="submitUpload"
    :limit="1"
    :accept="acceptStr"
    :before-upload="beforeUpload"
    :on-exceed="onExceed"
    :file-list="fileList"
>
<el-button type="primary" size="mini">选择文件</el-button>
</el-upload>

//预览小图,点击出现弹框
<img
    :src="localUrl"
    :title="imgTitle"
    width="200"
    height="200"
    style="cursor: pointer"
    v-on:click="previewBtnClick"
    />
    //弹框,查看大图,或者播放视频
        <el-dialog
          title="预览"
          :visible.sync="previewDialogVisible"
          width="50%"
          append-to-body
          style="background: unset"
          class="previewDialog"
        >
          <img
            :src="localUrl"
            alt=""
            width="500"
            height="500"
            v-if="uploadType==='image'"
          />
          <video
            :src="localSrc"
            controls
            width="100%"
            height="500px"
            autoplay
            muted
            loop
            v-else-if="uploadType==='video'"
            id="video"
          ></video>
        </el-dialog>
//提示用户只能选择一个文件
    onExceed() {
      this.$message.error('一次只能上传一个文件');
    },
    //当删除上传时,把预览小图还原成默认图片,上传类型还原
    handleRemove() {
      this.localUrl = this.previewImg;
      this.uploadType = '';
    },
    //要求用户,先选择好类型,再选择文件,如果用户在选择文件时把选择类型变为*时,选择不符合当前类型的文件,提示用户
        beforeUpload(file) {
      if (!this.acceptStr) {
        this.$message.error('请先选择实体类型');
        return false;
      }
      let acceptArr = this.acceptStr.replace(/\./g, '').split(',');
      if (!acceptArr.includes(file.name.split('.')[1].toUpperCase())) {
        this.$message.error('请选择符合实体类型的文件');
        return false;
      } else {
        return true;
      }
    },
    //上传 保存文件对象用于传给后端,通过FileReader对象,得到url用于图片和视频
     submitUpload(params) {
      this.fileObj = params.file;
      this.fileName = this.fileObj.name;
      const file = params.file;
      const type = file.type.split('/')[0];
      if (type === 'image') {
        this.uploadType = 'image';
        let imageReader = new FileReader();
        imageReader.readAsDataURL(file);
        imageReader.onload = () => {
          this.localUrl = imageReader.result;
          this.imgTitle = '点击预览';
        };
      } else if (type === 'video') {
        this.uploadType = 'video';
        let videoReader = new FileReader();
        videoReader.readAsDataURL(file);
        videoReader.onload = () => {
          this.localUrl = `${ctxPath}/static/wjImg/${this.uploadType}.jpeg`;
          this.localSrc = videoReader.result;
          this.imgTitle = '点击预览';
        };
      } else {
        this.uploadType = 'other';
        this.localUrl = `${ctxPath}/static/wjImg/default.jpg`;
        this.imgTitle = '点击下载';
      }
    },
    //当用户点击预览大图时,预览图片和播放视频,其他类型如(word)进行下载
        previewBtnClick() {
      if (['image', 'video'].includes(this.uploadType)) {
        this.previewDialogVisible = true;
      } else if (this.uploadType === 'other') {
        this.downloadFile(this.fileObj, this.fileName);
      }
    },
    //下载功能,如(word,excel,pdf)
        downloadFile(file, name) {
      let downloadElement = document.createElement('a');
      // // 创建下载的链接
      let href = window.URL.createObjectURL(file);
      downloadElement.href = href;
      // 下载后文件名
      downloadElement.download = name;
      document.body.appendChild(downloadElement);
      // 点击下载
      downloadElement.click();
      // 下载完成移除元素
      document.body.removeChild(downloadElement);
      // 释放掉blob对象
      window.URL.revokeObjectURL(href);
    },

传给后端时,选择formData形式:


        const form = new FormData();
        form.append('uFile', this.fileObj);
//把其他参数变成json字符串传给后端,最后设置响应头。
        form.append('paramJsonStr', JSON.stringify(params));
          axios({
            url: '/apiTrainIetm/commonDocument/insertCommonDocument',
            method: 'post',
            data: form,
            headers: {
              'Content-Type': 'multipart/form-data',
            },

回显,后端返回文件流,前端通过blob接收:

在请求时,设置请求的  responseType: 'blob',

const res = await axios(
        '/apiTrainIetm/commonDocument/selectFileByFilePath',
        {
          params: {
            filePath: comFilePath,
          },
          responseType: 'blob',
        }
      );
      let blob = res.data;
      //把blob转换为file对象,因为后端需要的是这个对象。
      this.fileObj = new File([blob], this.fileName);
      let href = window.URL.createObjectURL(blob);
      //解析blob类型转换为blob的url,用于图片显示和播放视频
      this.fileList.push({
        name: this.fileName,
        url: href,
      });
      if (this.docTypeList.includes(this.extension.toUpperCase())) {
        this.uploadType = 'other';
        this.localUrl = `${ctxPath}/static/wjImg/default.jpg`;
      } else if (this.videoTypeList.includes(this.extension.toUpperCase())) {
        this.uploadType = 'video';
        this.localUrl = `${ctxPath}/static/wjImg/video.jpeg`;
        this.localSrc = href;
      } else {
        this.uploadType = 'image';
        this.localUrl = href;
      }