vue项目中实现doc/excel/pdf/图片等文件的预览

vue项目中实现doc/excel/pdf/图片等文件的预览

word预览

1. 使用vue-office-docx(只支持docx文件预览,不支持doc文件)

支持文档网络地址(https://***.docx)。
文件上传时预览,此时可以获取文件的ArrayBuffer或二进制文件预览Blob。

// docx文档预览组件
npm install @vue-office/docx vue-demi@0.13.11
// 如果是vue2.6版本或以下还需要额外安装 @vue/composition-api
npm install @vue/composition-api/

<template>
  <vue-office-docx  :src="docx" style="height: 100vh;" @rendered="rendered" />
</template>
<script>
//引入VueOfficeDocx组件
import VueOfficeDocx from '@vue-office/docx'
//引入相关样式
import '@vue-office/docx/lib/index.css'
export default {
  components:{
    VueOfficeDocx
  },
  data(){
    return {
      docx: 'http://static.shanhuxueyuan.com/test6.docx' //设置文档网络地址,可以是相对地址
    }
  },
  methods:{
    rendered(){
      console.log("渲染完成")
    }
  }
}
</script>

2. 使用docx-preview

npm install docx-preview
import { renderAsync } from 'docx-preview';
// 调用函数,解析docx文件
renderAsync(res.data, document.getElementById("preload_box"), null, {
   className: "docx", // 默认和文档样式类的类名/前缀
   inWrapper: true, // 启用围绕文档内容渲染包装器
   ignoreWidth: false, // 禁止页面渲染宽度
   ignoreHeight: false, // 禁止页面渲染高度
   ignoreFonts: false, // 禁止字体渲染
   breakPages: true, // 在分页符上启用分页
   ignoreLastRenderedPageBreak: true, //禁用lastRenderedPageBreak元素的分页
   experimental: false, //启用实验性功能(制表符停止计算)
   trimXmlDeclaration: true, //如果为真,xml声明将在解析之前从xml文档中删除
   debug: false, // 启用额外的日志记录
})

3. 使用mammoth.js

npm install --save mammoth
import mammoth from “mammoth”;

<div ref='docpreview'></div>
mammoth.convertToHtml({path: "path/to/document.docx"})
    .then(function(result){
        var html = result.value; // The generated HTML
        this.$refs.docpreview.innerHTML = html
    })
    .catch(function(error) {
        console.error(error);
    });

4. 使用微软的Office Web Viewer

使用iframe作为载体。
文件会传输到微软的服务器上,因此可能会涉及到文件隐私。
不需要安装 Office 软件,直接通过浏览器在线预览 docx、xlsx、pptx 文件。
不支持 pdf 预览。

<iframe class="previewOffice" :src="officeUrl"></iframe>
const url = 'https:***/demo.pdf'
this.officeUrl = `https://view.officeapps.live.com/op/view.aspx?src=${url}`

5. 第三方服务接口地址:XDOC文档预览服务

excel预览

1. 使用vue-office-excel(只支持xlsx文件预览,不支持xls文件)

支持文档网络地址(https://***.xlsx)。
文件上传时预览,此时可以获取文件的ArrayBuffer或二进制文件预览Blob。

// excel文档预览组件
npm install @vue-office/excel vue-demi@0.13.11
// 如果是vue2.6版本或以下还需要额外安装 @vue/composition-api
npm install @vue/composition-api/

<template>
    <vue-office-excel :src="excel" style="height: 100vh;" @rendered="renderedHandler" @error="errorHandler" />
</template>
<script>
//引入VueOfficeExcel组件
import VueOfficeExcel from '@vue-office/excel'
//引入相关样式
import '@vue-office/excel/lib/index.css'
export default {
    components: {
        VueOfficeExcel
    },
    data() {
        return {
            excel: 'http://static.shanhuxueyuan.com/demo/excel.xlsx'//设置文档地址
        }
    },
    methods: {
        renderedHandler() {
            console.log("渲染完成")
        },
        errorHandler() {
            console.log("渲染失败")
        }
    }
}
</script>

2. 使用xlsx/sheetjs(需要自己排版)

xlsx插件只是帮助解析excel表中的数据,并不会进行排版,所以需要自己写样式重新排列数据。

npm install xlsx
import * as XLSX from 'xlsx/xlsx.mjs'

<el-table :data="excelData" style="width: 100%">
   <el-table-column
     v-for="(value, key, index) in excelData[0]"
     :key="index"
     :prop="key"
     :label="key"
   ></el-table-column>
</el-table>
 const xlsx_data = await res.data.arrayBuffer()
 let tem_workbook = XLSX.read(xlsx_data, {type:"array"}); // 解析数据
 workbook.value = tem_workbook
 getTable(tem_workbook.SheetNames[0]); // 读取第一张表数据
 
 // 解析xlsx数据为table
 function getTable(sheetName) {
    let worksheet = workbook.value.Sheets[sheetName];
    excelData.value = XLSX.utils.sheet_to_json(worksheet);
 }

3. 使用SpreadJS

4.使用luckysheet(支持在线编辑,目前只支持xlsx格式)

// 在inde.html文件中引入
<link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/luckysheet@latest/dist/plugins/css/pluginsCss.css' />
<link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/luckysheet@latest/dist/plugins/plugins.css' />
<link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/luckysheet@latest/dist/css/luckysheet.css' />
<link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/luckysheet@latest/dist/assets/iconfont/iconfont.css' />
<script src="https://cdn.jsdelivr.net/npm/luckysheet@latest/dist/plugins/js/plugin.js"></script>
<script src="https://cdn.jsdelivr.net/npm/luckysheet@latest/dist/luckysheet.umd.js"></script>

<div id="luckysheet" style="margin:0px;padding:0px;position:absolute;width:100%;height:100%;left: 0px;top: 0px;"></div>

mounted() {
	this.initLuckysheet()
},
methods: {
initLuckysheet() {
    $(function() {
      // 配置项
      var options = {
        container: 'luckysheet', // luckysheet为容器id
        showinfobar: false, // 信息栏
        lang: 'zh'// 设定表格语言
        // loadUrl:''
      }
      luckysheet.create(options)
    })
  },
}

pdf预览

1. 使用vue-office-pdf

支持文档网络地址(https://***.docx)。
文件上传时预览,此时可以获取文件的ArrayBuffer或二进制文件预览Blob。

// pdf文档预览组件
npm install @vue-office/pdf vue-demi@0.13.11
// 如果是vue2.6版本或以下还需要额外安装 @vue/composition-api
npm install @vue/composition-api/

<template>
    <vue-office-pdf :src="pdf" @rendered="renderedHandler" @error="errorHandler" />
</template>
<script>
//引入VueOfficePdf组件
import VueOfficePdf from '@vue-office/pdf'
export default {
    components: {
        VueOfficePdf
    },
    data() {
        return {
            pdf: 'http://static.shanhuxueyuan.com/test.pdf' //设置文档地址
        }
    },
    methods: {
        renderedHandler() {
            console.log("渲染完成")
        },
        errorHandler() {
            console.log("渲染失败")
        }
    }
}
</script>

2. 使用pdf-dist

为了正确解析pdf,将pdf文件流转化为一个blob的地址去被解析器读取。由于插件每次只能查询pdf文件一页数据,所以需要额外编写翻页的逻辑代码。被pdf渲染的元素pdf_canvas必须是canvas标签。

npm install pdfjs-dist
import * as PDFJS from "pdfjs-dist/legacy/build/pdf";  // 引入PDFJS 
import pdfjsWorker from "pdfjs-dist/legacy/build/pdf.worker.entry.js"; // 引入workerSrc的地址
// 调用函数,解析pdf文件
const blobPdf = new window.Blob([res.data], { type: 'application/pdf;chaset-UTF-8' })
const pdfhref = URL.createObjectURL(blobPdf);
PDFJS.getDocument(pdfhref).promise.then(pdfDoc=>{
   const numPages = pdfDoc.numPages; // pdf的总页数
   // 获取第1页的数据
   pdfDoc.getPage(1).then(page =>{
      // 设置canvas相关的属性
      const canvas = document.getElementById("pdf_canvas");
      const ctx = canvas.getContext("2d");
      const dpr = window.devicePixelRatio || 1;
      const bsr =
      ctx.webkitBackingStorePixelRatio ||
      ctx.mozBackingStorePixelRatio ||
      ctx.msBackingStorePixelRatio ||
      ctx.oBackingStorePixelRatio ||
      ctx.backingStorePixelRatio ||
      1;
      const ratio = dpr / bsr;
      const viewport = page.getViewport({ scale: 1 });
      canvas.width = viewport.width * ratio;
      canvas.height = viewport.height * ratio;
      canvas.style.width = viewport.width + "px";
      canvas.style.height = viewport.height + "px";
      ctx.setTransform(ratio, 0, 0, ratio, 0, 0);
      const renderContext = {
      canvasContext: ctx,
      viewport: viewport,
   };
   // 数据渲染到canvas画布上
   page.render(renderContext);
  })
})

// 切换pdf页数
function changePdfPage (type) {
  if (type == 'pre') {
    if (pdfPage.value <= 1) {
      ElMessage.error('没有上一页了');
      return 
    }
    pdfPage.value -= 1
  } else {
    if (pdfPage.value >= pdfValue.numPages) {
      ElMessage.error('没有下一页了');
      return 
    }
    pdfPage.value += 1
  }
  initPdfPage()
}

// 重新初始化pdf对应页数
function initPdfPage () {
  pdfValue.getPage(pdfPage.value).then(page =>{
    // 设置canvas相关的属性
    const canvas = document.getElementById("pdf_canvas");
    const ctx = canvas.getContext("2d");
    const dpr = window.devicePixelRatio || 1;
    const bsr =
      ctx.webkitBackingStorePixelRatio ||
      ctx.mozBackingStorePixelRatio ||
      ctx.msBackingStorePixelRatio ||
      ctx.oBackingStorePixelRatio ||
      ctx.backingStorePixelRatio ||
      1;
    const ratio = dpr / bsr;
    const viewport = page.getViewport({ scale: 1 });
    canvas.width = viewport.width * ratio;
    canvas.height = viewport.height * ratio;
    canvas.style.width = viewport.width + "px";
    canvas.style.height = viewport.height + "px";
    ctx.setTransform(ratio, 0, 0, ratio, 0, 0);
    const renderContext = {
      canvasContext: ctx,
      viewport: viewport,
    };
    // 数据渲染到canvas画布上
    page.render(renderContext);
  })
}

3. 使用vue-pdf

npm install vue-pdf
import pdf from 'vue-pdf'
components: {
	pdf
},
<pdf class="pdf-preview" style="width: 100%;height:100%" ref="myPdfComponent" :src="previewUrl"></pdf>

4. 使用iframe

<iframe :src='previewUrl' frameborder="0" width="100%" height="100%"></iframe>

图片预览

使用文件流预览

const blobImage = new window.Blob([res.data], { type: 'image/' + fileType }) // fileType指图片的类型
const imageHref = URL.createObjectURL(blobImage); // 创造一个地址
preloadImg.value = imageHref // img标签的src属性的值

使用v-viewer

// 全局引入(main.js中)
import 'viewerjs/dist/viewer.css'
import Viewer from 'v-viewer'
Vue.use(Viewer)
//配置项
Viewer.setDefaults({
  zIndexInline:9999
})

<!--1、以组件的形式-->
<viewer :images="photo">
  <img v-for="(src,index) in photo" :src="src" :key="index"/> 
</viewer>

<!--2、以指令的形式-->
只需要将v-viewer指令添加到任意元素即可,该元素下的所有img元素都会被viewer自动处理。
<div v-viewer>
  <img v-for="(src,index) in photo" :src="src" :key="index"/> 
</div>

链接

  • vue-office官方
  • sheetjs
  • 链接1
  • XDOC文档预览服务
  • luckysheet
  • Office Web Viewer
  • 链接2

你可能感兴趣的:(vue,excel,pdf)