vue 预览docx、pdf、xls、xlsx文件

vue 预览docx、pdf、xls、xlsx文件

office官方提供了office文件的预览,但是需要有域名与公网能访问到才行
官网预览方式,src后加你的文件路径

https://view.officeapps.live.com/op/view.aspx?src=
官网

内网预览插件(代码在文末)

pdf预览插件(vue-pdf)

安装

npm install --save vue-pdf

使用

在需要使用的文件中引入即可
import pdf from “vue-pdf”

样例
vue 预览docx、pdf、xls、xlsx文件_第1张图片

docx预览插件(mammoth)

该插件主要是把源文档转成了html,不支持doc文件
安装

npm install --save mammoth

使用

在需要使用的文件中引入即可
import mammoth from ‘mammoth’

xls、xlsx文件插件(xlsx)

安装

npm install xlsx -s

使用

同上,引入即可
import XLSX from “xlsx”

组件最终代码贴上

<template>
  <div>
    <el-dialog :visible="visible" :close-on-press-escape="false" :close-on-click-modal="false" append-to-body
               @close="handleClose" width="800px" :fullscreen="fullscreen">
      <template slot="title">
        <div class="dialog-title ellipsis">
          <div style="width: calc(100% - 20px);display: inline;">
            文件预览({{ file.name }})
          div>
          <div class="full-screen__menu" @click="fullscreen? fullscreen=false: fullscreen=true">
            <i class="el-icon-full-screen">i>
          div>
        div>
      template>
      <div>
        
        <div v-if="fileType===1">
          <div v-if="pdfData.pageCount>1">
            <el-button type="primary" size="mini" @click="changePdfPage(0)" icon="el-icon-arrow-left">el-button>
            <span style="font-size: 14px;font-weight: 550;margin: 0 10px">{{ pdfData.currentPage }} / {{
                pdfData.pageCount
              }}span>
            <el-button type="primary" size="mini" @click="changePdfPage(1)" icon="el-icon-arrow-right">el-button>
          div>
          <div
            :style="{height:fullscreen?(clientHeight-200)+'px':(clientHeight-400>800?800:clientHeight-400)+'px'}"
            style="margin-top: 5px;border: 1px solid #a0a0a0;overflow:auto;">
            <pdf
              :src="pdfData.src"
              :page="pdfData.currentPage"
              @num-pages="pdfData.pageCount=$event"
              @page-loaded="pdfData.currentPage=$event"
            >pdf>
          div>
        div>
        
        <div v-if="fileType===2">
          <div
            :style="{height:fullscreen?(clientHeight-200)+'px':(clientHeight-400>800?800:clientHeight-400)+'px'}"
            style="margin-top: 5px;border: 1px solid #a0a0a0;overflow: auto">
            <div v-html="docHtml" style="padding: 10px 15px">div>
          div>
        div>
        
        <div v-if="fileType===3">
          <div class="tab">
            <el-radio-group size="small" v-model="excel.sheetNameActive" @change="getSheetNameTable">
              <el-radio-button v-for="(item,index) in excel.sheetNames" :key="index" :label="item">el-radio-button>
            el-radio-group>
          div>
          <div
            :style="{height:fullscreen?(clientHeight-200)+'px':(clientHeight-400>800?800:clientHeight-400)+'px'}"
            style="margin-top: 5px;border: 1px solid #a0a0a0;overflow:auto;">
            <div v-html="excel.SheetActiveTable" style="padding: 10px 15px">div>
          div>
        div>
        <div v-if="!fileType" style="line-height: 50px;text-align: center;font-size: 16px">
          文件格式不支持,仅支持pdf,docx,xlsx,xls文件预览
        div>
      div>
      <div style="text-align: right;margin-top: 5px">
        <el-button size="small" @click="handleClose" class="raise">关闭el-button>
      div>
    el-dialog>
  div>
template>

<script>
import XLSX from "xlsx"
import pdf from "vue-pdf"
import mammoth from 'mammoth'

export default {
  name: "officePreview",
  props: {
    visible: {
      type: Boolean,
      default: false
    },
    // file:{name:'',url:''}
    file: {
      type: Object,
      default: () => {
        return {}
      }
    },
    // 弹窗高度
    clientHeight: {
      type: Number,
      default: 600
    },
    // 基础链接
    baseURL: {
      type: String,
      default: undefined
    }
  },
  data() {
    return {
      // 全屏
      fullscreen: false,
      // 文件类型
      fileType: 1,
      // pdf数据
      pdfData: {
        // 当前页
        currentPage: 1,
        // pdf文件总页数
        pageCount: 0,
        //
        src: ""
      },
      docHtml: "",
      // 空文件提示信息
      emptyTips: '暂无内容',
      // Excel文档数据
      excel: {
        // 数据
        workbook: {},
        // 表名称集合
        sheetNames: [],
        // 激活项
        sheetNameActive: "",
        // 当前激活表格
        SheetActiveTable: ""
      }
    }
  },
  methods: {
    handleClose() {
      this.$emit("update:visible", false)
    },
    /**
     * 切换pdf显示页
     * @param command
     */
    changePdfPage(command) {
      if (command === 0) {
        if (this.pdfData.currentPage > 1) {
          this.pdfData.currentPage--
        }
      } else if (command === 1) {
        if (this.pdfData.currentPage < this.pdfData.pageCount) {
          this.pdfData.currentPage++
        }
      }
    },
    /**
     * 获取文件类型
     * @return {null|number}
     */
    getFileType() {
      if (!this.file) {
        return null
      }
      let fileName = this.file.name.lastIndexOf(".");//取到文件名开始到最后一个点的长度
      let fileNameLength = this.file.name.length;//取到文件名长度
      let fileFormat = this.file.name.substring(fileName + 1, fileNameLength);//截
      console.log(fileFormat)
      if (fileFormat.toLowerCase() === "pdf") {
        return 1
      } else if (fileFormat.toLowerCase() === "docx") {
        return 2
      } else if (fileFormat.toLowerCase() === "xlsx" || fileFormat.toLowerCase() === "xls") {
        return 3
      }
      return null
    },
    /**
     * pdf预览
     */
    initPdf() {
      // this.pdfData.src = pdf.createLoadingTask(this.$baseURL + this.file.url)
      try {
        // 加载
        let _this = this
        const xhr = new XMLHttpRequest();
        xhr.open('get', this.baseURL + this.file.url, true);
        xhr.responseType = 'blob';
        xhr.onload = function () {
          if (xhr.status === 200) {
            _this.pdfData.src = _this.getObjectURL(xhr.response)
          } else if (xhr.status === 404) {
            _this.$error({message: "文件不存在"})
          } else {
            _this.$error({message: "读取服务器文档异常"})
          }
        }
        xhr.onerror = function () {
          _this.$error({message: "访问服务器异常,请检查访问链接是否正常"})
        }
        xhr.send();
      } catch (e) {
        console.log(e)
      }
    },
    /**
     * 将返回的流数据转换为url
     * @param file 文件流
     */
    getObjectURL(file) {
      let url = null;
      if (window.createObjectURL !== undefined) { // basic
        url = window.createObjectURL(file);
      } else if (window.webkitURL !== undefined) { // webkit or chrome
        try {
          url = window.webkitURL.createObjectURL(file);
        } catch (error) {

        }
      } else if (window.URL !== undefined) { // mozilla(firefox)
        try {
          url = window.URL.createObjectURL(file);
        } catch (error) {
          console.log(error)
        }
      }
      return url;
    },
    /**
     * docx文件预览
     */
    initDocPreview() {
      // 请求文件流
      try {
        let _this = this
        const xhr = new XMLHttpRequest();
        xhr.open('get', this.baseURL + this.file.url, true);
        xhr.responseType = 'arraybuffer';
        xhr.onload = function () {
          if (xhr.status === 200) {
            mammoth.convertToHtml({arrayBuffer: new Uint8Array(xhr.response)}).then(function (resultObject) {
              _this.docHtml = resultObject.value
            })
          } else if (xhr.status === 404) {
            _this.$error({message: "文件不存在"})
          } else {
            _this.$error({message: "读取服务器文档异常"})
          }
        }
        xhr.onerror = function () {
          _this.$error({message: "访问服务器异常,请检查访问链接是否正常"})
        }
        xhr.send();
      } catch (e) {
        this.docHtml = '

' + this.emptyTips + '

'
} }, /** * 表格数据预览 */ initExcelPreview() { try { let xhr = new XMLHttpRequest() xhr.open('get', this.baseURL + this.file.url, true) xhr.responseType = 'arraybuffer' const _this = this xhr.onload = function (e) { if (xhr.status === 200) { const data = new Uint8Array(xhr.response) const workbook = XLSX.read(data, {type: 'array'}) const sheetNames = workbook.SheetNames // 工作表名称集合 _this.excel.workbook = workbook _this.excel.sheetNames = sheetNames _this.excel.sheetNameActive = sheetNames[0] _this.getSheetNameTable(sheetNames[0]) } else if (xhr.status === 404) { _this.$error({message: "文件不存在"}) } else { _this.$error({message: "读取服务器文档异常"}) } } xhr.onerror = function () { _this.$error({message: "访问服务器异常,请检查访问链接是否正常"}) } xhr.send() } catch (e) { console.log(e) } }, /** * 根据工作表名称获取数据 * @param sheetName */ getSheetNameTable(sheetName) { try { // 获取当前工作表的数据 const worksheet = this.excel.workbook.Sheets[sheetName] // 转换为数据 1.json数据有些问题,2.如果是html那么样式需修改 let htmlData = XLSX.utils.sheet_to_html(worksheet, {header: '', footer: ''}) htmlData = htmlData === '' ? htmlData : htmlData.replace(//, ')// 第一行进行改颜色 htmlData = htmlData ===''? htmlData : htmlData.replace(//, ')this.excel.SheetActiveTable = htmlData }catch(e){// 如果工作表没有数据则到这里来处理this.excel.SheetActiveTable ='

' + this.emptyTips + '

'
}},},created(){this.fileType =this.getFileType()if(this.fileType ===1){this.initPdf()}if(this.fileType ===2){this.initDocPreview()}if(this.fileType ===3){this.initExcelPreview()}}, components:{ pdf }}script> <style scoped> .dialog-title { text-align: center; display: flex; font-size: 18px; width: calc(100% - 30px); } .full-screen__menu { font-size: 16px; display: inline; } .full-screen__menu:hover { font-size: 16px; color: #2D8CF0; } style> <style> table.default-table { /* -moz-border-radius: 5px; -webkit-border-radius:5px; border-radius:5px; */ width: 100%; border: solid #333; border-width: 1px 0px 0px 1px; font-size: 16px; border-collapse: collapse; border-spacing: 0; } table.default-table tbody tr { height: 20px; line-height: 20px; white-space: nowrap; } table.default-table tbody tr:hover { background-color: #eee; } table.default-table tbody tr th, table.default-table tbody tr td { padding: 3px 5px; text-align: left; /* border: 1px solid #ddd; */ border: solid #333; border-width: 0px 1px 1px 0px; white-space: nowrap; } table.default-table tbody tr th { font-weight: bold; text-align: center; } table.default-table tbody tr td a:hover { color: #0080c0; } style>

组件使用

将组件导入要使用的文件中即可

import officePreview from "../../../components/officePreview";
components: {
	officePreview
}
<office-preview :visible.sync="previewVisible" v-if="previewVisible" :client-height="clientHeight"
                    :file="previewFile" :base-u-r-l="officeURL">office-preview>

你可能感兴趣的:(vue,html,vue.js,css3)