vue在线预览文件,支持(docx、xlsx、pdf)

在线预览文件docx、xslx、pdf、img

在项目中比如要对上传的文件进行预览,这时前端通常采用的是使用各种库来解决这个问题。这里推荐一个库vue-office,vue-office是一站式解决(docx、.xlsx、pdf)预览的vue组件库。

vue在线预览文件,支持(docx、xlsx、pdf)_第1张图片

可以看出这个组件库还是有些缺陷的,比如docx的艺术字体、excel的多种数据格式解析不准确的问题,但普通的预览是没什么问题的。

为什么基本找不到doc或xls的在线预览,首先doc和xls是07版本前的格式,其次docx和xlsx是采用XML的开放文件格式进行存储,解析更容易。所以市面上基本都是docx和xlsx更容易找到方案,要能够预览doc和xls一般要花费较大的成本。

pdf

相对于文档和表格pdf的库是比较多的,以下为使用vue-office/pdf的示例:

<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' //设置文档地址,可以是base64
        }
    },
    methods: {
        renderedHandler() {
            console.log("渲染完成")
        },
        errorHandler() {
            console.log("渲染失败")
        }
    }
}
</script>

这个很简单直接放链接或base64编码就可以,这个是pdf实际就是基于pdfjs这个库,但在比较老的浏览器中兼容性并不好,检查是否支持“||=”,如果支持就直接使用vue-office/pdf这个库,如果不支持那么我们直接使用[email protected]这个库。

如果要对pdf进行放大缩小为了性能和用户友好,我们先把canvas画面放大,然后再通过css把盒子缩小,直接控制盒子的缩放就行,这样一来就不用重新渲染同时保证了画质的清晰度,一定程度上提升了性能。

使用示例如下:

<template>
  <div class="pdfcontainer">
    <div
      class="pdfcanvas"
      ref="pdfCanvasContainer"
      :style="'transform:scale(' + canvasScale + ')'"
    ></div>
    <div class="zoom">
      <i class="el-icon-zoom-out cursor" @click="zoom('out')"></i>
      <i class="el-icon-zoom-in cursor" @click="zoom('in')"></i>
    </div>
  </div>
</template>

<script>
import { getDocument } from "pdfjs-dist";

export default {
  name: "PdfViewer",
  props: {
    src: {
      type: String,
    },
  },
  data() {
    return {
      scale: 3,
      canvasScale: 0.5,
    };
  },
  mounted() {
    this.loadPdf();
  },
  methods: {
    /**
     * @description: 加载pdf
     */
    loadPdf() {
      let base64Data = this.src.replace(/^data:application\/pdf;base64,/, "");
      let pdfData = window.atob(base64Data);
      let arrayBuffer = new Uint8Array(pdfData.length);
      for (let i = 0; i < pdfData.length; i++) {
        arrayBuffer[i] = pdfData.charCodeAt(i);
      }
      const loadingTask = getDocument({ data: arrayBuffer });

      loadingTask.promise.then((pdf) => {
        const numPages = pdf.numPages;
        const canvasContainer = this.$refs.pdfCanvasContainer;
        canvasContainer.innerHTML = ""; // 清空容器
        for (let pageNumber = 1; pageNumber <= numPages; pageNumber++) {
          pdf.getPage(pageNumber).then((page) => {
            const viewport = page.getViewport(this.scale);
            const canvas = document.createElement("canvas");
            const context = canvas.getContext("2d");
            canvas.height = viewport.height || page.view[3];
            canvas.width = viewport.width || page.view[2];
            // 将canvas添加到容器中
            canvasContainer.appendChild(canvas);
            // 渲染PDF到canvas
            const renderContext = {
              canvasContext: context,
              viewport: viewport,
            };
            page.render(renderContext);
          });
        }
      });
    },
    /**
     * @description: 缩放
     * @param {String} type 类型
     */
    zoom(type) {
      if (type) {
        if (type === "out" && this.canvasScale.toFixed(2) > 0.1) {
          this.canvasScale -= 0.05;
        } else if (type === "in") {
          this.canvasScale += 0.05;
        }
      }
    },
  },
};
</script>
<style scoped>
.pdfcontainer {
  position: relative;
}
.pdfcanvas {
  position: absolute;
  top: 12px;
  left: 0;
  right: 0;
  bottom: 0;
  max-width: 100%;
  max-height: 100%;
}
.scale {
  position: fixed;
  bottom: 24px;
  right: 24px;
  font-size: 24px;
}
.cursor {
  margin: 24px;
  cursor: pointer;
}
</style>

docx

这个目前就使用vue-office/docx就能支持,在老本版中浏览器中也能使用,使用示例如下:

<template>
    <vue-office-docx
        :src="docx"
        style="height: 100vh;"
        @rendered="renderedHandler"
        @error="errorHandler"
    />
</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' //设置文档网络地址,可以是相对地址,也可以是base64
        }
    },
    methods: {
        renderedHandler() {
            console.log("渲染完成")
        },
        errorHandler() {
            console.log("渲染失败")
        }
    }
}
</script>

xlsx

这个目前就使用vue-office/excel就能支持,在老本版中浏览器中也能使用,使用示例如下:

<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'//设置文档地址,或base64
        }
    },
    methods: {
        renderedHandler() {
            console.log("渲染完成")
        },
        errorHandler() {
            console.log("渲染失败")
        }
    }
}
</script>

图片

图片直接使用img标签就行啦

总结

以上就是在线预览的一些方案啦,有更好的方式欢迎评论留言讨论。

你可能感兴趣的:(vue.js,pdf,前端,笔记)