vue中图片、office、pdf、视频等文件的预览以及下载

本文展示了如何在Vue中实现文件上传组件,包括限制上传数量、文件类型检查、上传成功回调、预览功能等。通过el-upload组件,结合before-upload钩子函数进行文件合法性检查,on-success回调处理上传成功后的操作,以及自定义预览组件展示不同类型的文件。
摘要由CSDN通过智能技术生成

上传

<template>
  <div>
    <el-upload
      ref="upload"
      :limit="CountNum"
      :on-remove="handleRemove"
      :on-error="onError"
      :file-list="urlArr"
      :on-success="handleAvatarSuccess"
      :before-upload="beforeAvatarUpload"
      :action="url"
      :on-preview="tabPreview"
      class="upload-demo"
      style="width: 450px"
    >
      <el-button slot="trigger" size="small" type="primary">上传附件</el-button>
      <div slot="tip" class="el-upload__tip">
        支持上传 {{ strRebuild(fileType) }} 格式,且不超过 {{ fileSize }}M
      </div>
    </el-upload>
    <FilePreview ref="filePreview"> </FilePreview>
  </div>
</template>
<script>
import { strRebuild, lastSubstring } from "@/utils/strUtil";
import { message } from "@/utils/message";
import FilePreview from "@/components/filePreview/index.vue";
export default {
  props: {
    urlArr: {
      type: Array,
      default: [],
    },

    CountNum: {
      type: Number,
      default: 1,
    },
  },
  components: {
    FilePreview,
  },
  data() {
    return {
      // 附件列表
      fileList: [],
      // 允许的文件类型
      fileType: [
        "xls",
        "xlsx",
        "pdf",
        "doc",
        "docx",
        // "mp4",
        "jpg",
        "png",
        "jpeg",
      ],
      // 运行上传文件大小,单位 M
      fileSize: 10,
    };
  },
  created() {
    this.url = this.uploadURL;
  },
  methods: {
    // 清空表单
    clear() {
      // 清空附件
      this.$refs.upload.clearFiles();
    },
    beforeAvatarUpload(file) {
      console.log(file);
      var flag = true;
      var tip = "";
      //   var files = this.$refs.upload.uploadFiles;
      // 文件过大
      if (file.size > this.fileSize * 1024 * 1024) {
        flag = false;
        tip = " 文件超过" + this.fileSize + "M";
      }
      //   console.log(this.fileType.includes(lastSubstring(file.name, ".")));
      // 文件类型不属于可上传的类型
      if (!this.fileType.includes(lastSubstring(file.name, "."))) {
        flag = false;
        tip = " 文件类型不可上传";
      }

      if (!flag) {
        message("error", tip);
      }
      return flag;
    },
    handleAvatarSuccess(res, file) {
      //   console.log(this.urlArr);

      if (res.code === 0) {
        let arr = this.urlArr;
        console.log(res.data);
        console.log(this.urlArr);
        arr.push({
          name: res.data,
          url: this.showURL + res.data,
        });
        this.$notify.success({
          title: "成功",
          message: "上传成功",
        });
        this.$emit("imgUrl", arr);
      } else {
        //   this.imageUrl = "";
      }
    },
    // 附件检查
    // 检查附件是否属于可上传类型
    // 检查附件是否超过限制大小
    checkFile() {
      var flag = true;
      var tip = "";
      var files = this.$refs.upload.uploadFiles;
      files.forEach((item) => {
        // 文件过大
        if (item.size > this.fileSize * 1024 * 1024) {
          flag = false;
          tip = " 文件超过" + this.fileSize + "M";
        }
        console.log(this.fileType.includes(lastSubstring(item.name, ".")));
        // 文件类型不属于可上传的类型
        if (!this.fileType.includes(lastSubstring(item.name, "."))) {
          flag = false;
          tip = " 文件类型不可上传";
        }
      });
      if (!flag) {
        message("error", tip);
      }
      return flag;
    },

    // 提交附件
    submitUpload() {
      if (this.checkFile()) {
        console.log("上传附件...");
        this.$refs.upload.submit();
      } else {
        console.log("取消上传");
      }
    },
    // 点击已上传文件
    tabPreview(file) {
      console.log(file);
      //  下载
      // if (file.name.indexOf("txt") == "-1") {
      //   console.log("d");
      //   const link = document.createElement("a");
      //   document.body.appendChild(link);
      //   link.style.display = "none";
      //   link.setAttribute(
      //     "href",
      //     file.url + "?response-content-type=application/octet-stream"
      //   ); //设置下载文件的url地址
      //   link.target = "_blank";
      //   document.body.appendChild(link);
      //   link.click();
      //   document.body.removeChild(link);
      // } else {
      //   let element = document.createElement("a");
      //   element.setAttribute(
      //     "href",
      //     "data:text/plain;charset=utf-8," + file.url
      //   );
      //   element.setAttribute("download", file.name);
      //   element.style.display = "none";
      //   element.click();
      // }

      // 预览
      this.$refs.filePreview.previewPdf(file);
    },
    // 自定义文件上传方法
    uploadFile(file) {
      // 把文件放入 FormData 进行提交
      //   const param = new FormData();
      //   param.append("files", file.file);
      //   uploadFile(param).then((response) => {
      //     // TODO 一些关闭弹框,上传成功提示等
      //   });
    },

    // 移除附件
    handleRemove(file, fileList) {
      console.log("移除附件...", file, fileList);
      let url = file.name;
      let index = this.urlArr.findIndex((v) => {
        return url === v.name;
      });
      this.urlArr.splice(index, 1);
      this.$emit("imgUrl", this.urlArr);
    },

    // 附件上传失败,打印下失败原因
    onError(err) {
      message("error", "附件上传失败");
      console.log(err);
    },

    // 字符串重组
    strRebuild(str) {
      return strRebuild(str);
    },
  },
};
</script>
<style lang="scss" scoped>
</style>

预览

<template>
  <div>
    <el-button @click="previewPdf()" type="text" size="small">
      <div class="images" v-viewer="{ navbar: false }">
        <img
          v-for="(src, index) in images"
          style="width: 100%"
          :src="src"
          :key="src"
          hidden
        />
        <!-- 预览 -->
      </div>
    </el-button>

    <el-dialog
      :visible="showDoc == true || showPdf == true || showVideo == true"
      :show-close="true"
      :width="'80%'"
      top="5vh"
      class="dialog-div-pre-style"
      :before-close="closePreviewClick"
      center
    >
      <div v-if="showDoc == true" class="dialog-body-content-base-style">
        <iframe
          frameborder="0"
          :src="
            'https://view.officeapps.live.com/op/view.aspx?src=' + this.fileUrl
          "
          width="100%"
          style="min-height: 800px; height: 100%"
        >
        </iframe>
      </div>
      <div
        v-else-if="showPdf == true"
        class="dialog-body-content-base-style"
        style="justify-content: center; align-items: center"
      >
        <embed
          :src="pdfUrl"
          style="width: 100%; min-height: 800px; height: 100%"
        />
      </div>
      <div
        v-else-if="showVideo == true"
        class="dialog-body-content-base-style"
        style="justify-content: center; align-items: center"
      >
        <video-player
          class="video-player vjs-custom-skin"
          ref="positiveVideoPlayer"
          :playsinline="true"
          :options="positivePlayerOptions"
        ></video-player>
      </div>
    </el-dialog>
  </div>
</template>
<script>
export default {
  data() {
    return {
      showDoc: false,
      showPdf: false,
      showVideo: false,
      fileUrl: "",
      images: [],
      currentPage: 0, // pdf文件页码
      pageCount: 0, // pdf文件总页数
      pdfUrl: "",
      scale: 1.0,
      /**
       *播放器配置
       */
      positivePlayerOptions: {
        playbackRates: [0.5, 1.0, 1.5, 2.0], //播放速度
        autoplay: false, //如果true,浏览器准备好时开始回放。
        muted: false, // 默认情况下将会消除任何音频。
        loop: false, // 导致视频一结束就重新开始。
        preload: "auto", // 建议浏览器在<video>加载元素后是否应该开始下载视频数据。auto浏览器选择最佳行为,立即开始加载视频(如果浏览器支持)
        language: "zh-CN",
        aspectRatio: "16:9", // 将播放器置于流畅模式,并在计算播放器的动态大小时使用该值。值应该代表一个比例 - 用冒号分隔的两个数字(例如"16:9"或"4:3")
        fluid: true, // 当true时,Video.js player将拥有流体大小。换句话说,它将按比例缩放以适应其容器。
        sources: [
          {
            type: "",
            src: "", //视频url地址
          },
        ],
        poster: "", //你的封面地址
        // width: document.documentElement.clientWidth,
        notSupportedMessage: "此视频暂无法播放,请稍后再试", //允许覆盖Video.js无法播放媒体源时显示的默认信息。
        controlBar: {
          timeDivider: true,
          durationDisplay: true,
          remainingTimeDisplay: false,
          fullscreenToggle: true, //全屏按钮
        },
        common: "positivePlayer",
      },
    };
  },
  methods: {
    /**
     * pdf预览
     */
    previewPdf(row) {
      //   console.log(row);
      //   let row = {
      //     name: "/2022/02/10/1644470876079565.jpg",
      //     url: "http://nongmuren.oss-cn-qingdao.aliyuncs.com/zgt/2022/02/10/1644470876079565.jpg",
      //   };
      let type = this.iconByType(row);
      this.fileUrl = row.url;
      if (
        type.indexOf("doc") != -1 ||
        type.indexOf("docx") != -1 ||
        type.indexOf("xsl") != -1 ||
        type.indexOf("xslx") != -1
      ) {
        this.showDoc = true;
      } else if (type.indexOf("pdf") != -1) {
        this.pdfUrl = row.url;
        //   "http://nongmuren.oss-cn-qingdao.aliyuncs.com/zgt/2022/02/10/1644460353721288.pdf";
        this.showPdf = true;
      } else if (
        type.indexOf("jpg") != -1 ||
        type.indexOf("png") != -1 ||
        type.indexOf("jpeg") != -1
      ) {
        this.images = [row.url];
        const viewer = this.$el.querySelector(".images").$viewer;
        viewer.show();
      } else if (
        type.indexOf("avi") != -1 ||
        type.indexOf("mp4") != -1 ||
        type.indexOf("webm") != -1 ||
        type.indexOf("m4v") != -1 ||
        type.indexOf("rmvb") != -1 ||
        type.indexOf("mpg") != -1 ||
        type.indexOf("3gp") != -1 ||
        type.indexOf("swf") != -1 ||
        type.indexOf("mkv") != -1
      ) {
        this.positivePlayerOptions.sources[0].src = row.url;

        this.positivePlayerOptions.sources[0].type = "video/mp4";
        this.showVideo = true;
      } else {
        this.$message("当前文件暂不支持预览");
      }
      // this.showPdf = true
    },
    /**
     * 通过文件后缀返回文件的图标
     */
    iconByType(row) {
      return row.name.substring(row.name.lastIndexOf(".") + 1, row.name.length);
    },
    closePreviewClick() {
      if (this.showDoc == true) {
        this.showDoc = false;
      } else if (this.showPdf == true) {
        this.showPdf = false;
      } else if (this.showVideo == true) {
        this.showVideo = false;
      }
    },
  },
};
</script>
  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值