vue 文件本地预览 -通过vue-office (pdf、xlsx、xls、doc、docx、ppt)

首先,按需拉取,依赖和项目对应的版本 ,引入方法,和调用方法,根据版本来

  • npm install @vue-office/docx
  • npm install @vue-office/pdf
  • npm install @vue-office/excel
  • npm install @vue-office/pptx
  • 根据版本,有的需要 npm install @vue/composition-api
image.png

如果pdf不需要修改样式,可以使用iframe

<template>
  <div id="docx-demo">
    <div class="file-info">
      <h3>正在预览: {{ selectedFile.name }}</h3>
      <p>文件大小: {{ formatFileSize(selectedFile.size) }}</p>
    </div>
    <div class="loading" v-if="loading">
      <div class="spinner"></div>
      <p>加载中,请稍候...</p>
    </div>
    <el-upload
      :limit="1"
      :file-list="fileList"
      :beforeUpload="beforeUpload"
      action=""
    >
      <el-button size="small" type="warning">点击上传</el-button>
    </el-upload>

    <vue-office-docx
      v-if="fileType === 'docx' || fileType === 'doc'"
      :src="src"
      @rendered="onRendered"
      @error="onError"
    />
    <vue-office-excel
      :src="excel"
      v-if="fileType === 'xlsx' || fileType === 'xls'"
      :options="options"
      style="height: 500px"
      @rendered="onRendered"
      @error="onError"
    />
    <vue-office-pdf
      v-if="fileType === 'pdf'"
      :src="pdf"
      style="height: 100vh"
      @rendered="onRendered"
      @error="onError"
    />
    <div
      class="custom-ppt-viewer"
      v-if="fileType === 'pptx' || fileType === 'ppt'"
    >
      <vue-office-pptx :src="ppt" @rendered="onRendered" @error="onError" />
    </div>
    <iframe
      :src="previewUrl"
      frameborder="0"
      class="pdf-iframe"
      @load="handleIframeLoad"
      @error="handleIframeError"
    ></iframe>
  </div>
</template>

<script>
import VueOfficeDocx from "@vue-office/docx";
import "@vue-office/docx/lib/index.css";
//引入VueOfficeExcel组件
import VueOfficeExcel from "@vue-office/excel";
//引入相关样式
import "@vue-office/excel/lib/index.css";
import VueOfficePdf from "@vue-office/pdf";
import VueOfficePptx from "@vue-office/pptx";

export default {
  components: {
    VueOfficeDocx,
    VueOfficeExcel,
    VueOfficePdf,
    VueOfficePptx,
  },
  data() {
    return {
      ppt: "",
      previewUrl: "",
      acceptTypes: ".docx,.xlsx,.pptx,.pdf",
      loading: false,
      fileType: "",
      selectedFile: { name: "", size: 0 },
      pdf: "",
      excel: "",
      src: "",
      fileList: [],
      options: {
        xls: false, //预览xlsx文件设为false;预览xls文件设为true
        // minColLength: 0, // excel最少渲染多少列,如果想实现xlsx文件内容有几列,就渲染几列,可以将此值设置为0.
        // minRowLength: 0, // excel最少渲染多少行,如果想实现根据xlsx实际函数渲染,可以将此值设置为0.
        widthOffset: 10, //如果渲染出来的结果感觉单元格宽度不够,可以在默认渲染的列表宽度上再加 Npx宽
        heightOffset: 10, //在默认渲染的列表高度上再加 Npx高
        beforeTransformData: (workbookData) => {
          return workbookData;
        }, //底层通过exceljs获取excel文件内容,通过该钩子函数,可以对获取的excel文件内容进行修改,比如某个单元格的数据显示不正确,可以在此自行修改每个单元格的value值。
        transformData: (workbookData) => {
          return workbookData;
        }, //将获取到的excel数据进行处理之后且渲染到页面之前,可通过transformData对即将渲染的数据及样式进行修改,此时每个单元格的text值就是即将渲染到页面上的内容
      },
    };
  },
  methods: {
    // 检查文件大小 (这里限制为10MB)
    // const maxSize = 10 * 1024 * 1024; // 10MB
    // if (file.size > maxSize) {
    //   this.errorMessage = '文件大小不能超过10MB';
    //   return;
    // }
    // 处理iframe加载完成
    handleIframeLoad() {
      console.log("PDF预览加载完成");
    },

    // 处理iframe加载错误
    handleIframeError() {
      this.errorMessage = "PDF预览失败,请尝试重新上传";
    },
    formatFileSize(bytes) {
      if (bytes === 0) return "0 Bytes";
      const k = 1024;
      const sizes = ["Bytes", "KB", "MB", "GB"];
      const i = Math.floor(Math.log(bytes) / Math.log(k));
      return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i];
    },
    onRendered() {
      this.loading = false;
      console.log("文档渲染完成");
    },
    onError(err) {
      this.loading = false;
      this.error = "文档预览失败: " + err.message;
      console.error("预览错误:", err);
    },
    //在beforeUpload中读取文件内容
    beforeUpload(file) {
      if (!file) return;
      this.selectedFile = file;
      this.error = "";
      this.loading = true;
      // 获取文件类型
      const fileName = file.name.toLowerCase();
      if (fileName.endsWith(".docx")) {
        this.fileType = "docx";
      } else if (fileName.endsWith(".doc")) {
        this.fileType = "doc";
      } else if (fileName.endsWith(".ppt")) {
        this.fileType = "ppt";
      } else if (fileName.endsWith(".xlsx")) {
        this.fileType = "xlsx";
      } else if (fileName.endsWith(".xls")) {
        this.fileType = "xls";
      } else if (fileName.endsWith(".pptx")) {
        this.fileType = "pptx";
      } else if (fileName.endsWith(".pdf")) {
        this.fileType = "pdf";
      } else if (fileName.endsWith(".txt")) {
        this.fileType = "txt";
      } else {
        this.error = "不支持的文件格式";
        this.loading = false;
        return;
      }
      let reader = new FileReader();
      reader.readAsArrayBuffer(file);
      reader.onload = (loadEvent) => {
        let arrayBuffer = loadEvent.target.result;
        if (this.fileType == "xlsx" || this.fileType == "xls") {
          this.excel = arrayBuffer;
        } else if (this.fileType == "docx" || this.fileType == "doc") {
          this.src = arrayBuffer;
        } else if (this.fileType == "pptx" || this.fileType == "ppt") {
          this.ppt = arrayBuffer;
        }
        if (this.fileType == "pdf" || this.fileType == "txt") {
          this.pdf = arrayBuffer;
          this.previewFile(file);
        }
      };

      return false;
    },
    // 预览PDF文件
    previewFile(file) {
      // 模拟上传进度
      this.uploadProgress = 0;
      const interval = setInterval(() => {
        this.uploadProgress += 10;
        if (this.uploadProgress >= 100) {
          clearInterval(interval);
          // 创建文件的临时URL用于预览
          this.previewUrl = URL.createObjectURL(file);
        }
      }, 200);
    },
  },
};
</script>
<style scoped>
.pdf-iframe {
  width: 100%;
  height: 400px;
}
.custom-ppt-viewer {
  width: 100%;
  max-width: 900px;
  margin: 0 auto;
  height: 700px;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}

.custom-ppt-viewer .slide-container {
  background-color: #f9f9f9;
  margin-bottom: 20px;
  border-radius: 8px;
  overflow: hidden;
}

</style>
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容