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”

样例
在这里插入图片描述

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>
        <!-- pdf预览 -->
        <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>
        <!-- word文档预览 -->
        <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>
        <!-- Excel文档预览 -->
        <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 = '<h1 style="text-align: center">' + this.emptyTips + '</h1>'
      }
    },
    /**
     * 表格数据预览
     */
    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(/<table/, '<table class="default-table" border="1px solid #ccc" cellpadding="0" cellspacing="0"')
        // 第一行进行改颜色
        htmlData = htmlData === '' ? htmlData : htmlData.replace(/<tr/, '<tr style="background:#b4c9e8"')
        this.excel.SheetActiveTable = htmlData
      } catch (e) {
        // 如果工作表没有数据则到这里来处理
        this.excel.SheetActiveTable = '<h4 style="text-align: center">' + this.emptyTips + '</h4>'
      }
    },
  },
  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>
  • 16
    点赞
  • 72
    收藏
    觉得还不错? 一键收藏
  • 15
    评论
Vue预览docx、doc、pdfxlsxlsx文件,可以使用第三方库来实现。 对于docx、doc、xlsxlsx文件,可以使用`js-xlsx`库来进行解析和预览。该库可以将Excel文件转换为JSON格式,而对于Word文件,可以使用`docx.js`库来进行解析和预览。 对于pdf文件,可以使用`pdf.js`库来进行预览。该库可以通过Canvas将PDF文件渲染成图片,然后在Vue中显示。 下面是一个示例代码,演示如何使用上述库来预览不同类型的文件: ```html <template> <div> <div v-if="fileType === 'docx' || fileType === 'doc'"> <div v-html="docContent"></div> </div> <div v-else-if="fileType === 'xls' || fileType === 'xlsx'"> <table> <tr v-for="row in excelData"> <td v-for="cell in row">{{ cell }}</td> </tr> </table> </div> <div v-else-if="fileType === 'pdf'"> <canvas ref="pdfCanvas"></canvas> </div> </div> </template> <script> import XLSX from 'xlsx'; import Docx from 'docx'; import pdfjsLib from 'pdfjs-dist'; export default { data() { return { fileType: '', docContent: '', excelData: [], }; }, mounted() { // 根据文件类型进行解析和预览 if (this.fileType === 'docx' || this.fileType === 'doc') { const reader = new FileReader(); reader.onload = (event) => { const content = event.target.result; const doc = new Docx(); doc.load(content); this.docContent = doc.getHtml(); }; reader.readAsArrayBuffer(this.file); } else if (this.fileType === 'xls' || this.fileType === 'xlsx') { const reader = new FileReader(); reader.onload = (event) => { const content = event.target.result; const workbook = XLSX.read(content, { type: 'array' }); const sheetName = workbook.SheetNames[0]; const worksheet = workbook.Sheets[sheetName]; this.excelData = XLSX.utils.sheet_to_json(worksheet, { header: 1 }); }; reader.readAsArrayBuffer(this.file); } else if (this.fileType === 'pdf') { const canvas = this.$refs.pdfCanvas; const ctx = canvas.getContext('2d'); pdfjsLib.getDocument(this.file).promise.then((pdf) => { pdf.getPage(1).then((page) => { const viewport = page.getViewport({ scale: 1.5 }); canvas.height = viewport.height; canvas.width = viewport.width; page.render({ canvasContext: ctx, viewport, }); }); }); } }, props: { file: { type: File, required: true, }, }, created() { // 根据文件后缀名判断文件类型 const fileExtension = this.file.name.split('.').pop(); if (fileExtension === 'docx' || fileExtension === 'doc') { this.fileType = 'docx'; } else if (fileExtension === 'xls' || fileExtension === 'xlsx') { this.fileType = 'xls'; } else if (fileExtension === 'pdf') { this.fileType = 'pdf'; } }, }; </script> ``` 在上述代码中,根据文件后缀名判断文件类型,然后使用不同的库进行解析和预览。对于Word文件,使用`docx.js`库将文件解析为HTML格式,然后在Vue中显示;对于Excel文件,使用`js-xlsx`库将文件解析为JSON格式,然后在Vue中生成表格;对于PDF文件,使用`pdf.js`库将文件渲染成图片,然后在Vue中显示。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值