之前做PDF预览一直用的pdf.js,这次没有太多附加需求比较简单简,所以决定用vue-pdf这个组件,虽然说它没有原生那样强大,但已经满足常用的需求了,重要是这个组件使用简单。顺便也把word文件和excel表格预览也整理了下,接下来我们直接进入正题!
一、预览word文件
1.安装 npm 依赖

npm i docx-preview@0.1.4
npm i jszip

2.预览在线地址文件

<template>
  <div class="home">
    <div ref="file"></div>
  </div>
</template>

<script>
import axios from 'axios'
const docx = require('docx-preview');
window.JSZip = require('jszip')
export default {
  mounted(){
    axios({
      method: 'get',
      responseType: 'blob', // 设置响应文件格式
      url: '/docx',
    }).then(({data}) => {
      docx.renderAsync(data,this.$refs.file) // 渲染到页面预览
    })
  }
}
</script>

3.预览本地文件

<template>
  <div class="my-component" ref="preview">
    <input type="file" @change="preview" ref="file">
  </div>
</template>
<script>
const docx = require('docx-preview');
window.JSZip = require('jszip')
export default {
  methods:{
    preview(e){
      docx.renderAsync(this.$refs.file.files[0],this.$refs.preview) // 渲染到页面预览
    }
  }
};
</script>
<style lang="less" scoped>
.my-component{
  width: 100%;
  height: 90vh;
  border: 1px solid #000;
}
</style>

二、预览excel表格
1.安装依赖

npm i xlsx

2.预览在线表格

<template>
  <div class="home">
    <div v-html="tableau"></div>
  </div>
</template>

<script>
import axios from 'axios'
import XLSX from "xlsx";
export default {
  data(){
    return {
      tableau: null,
    }
  },
  mounted(){
     axios.get('/xlsx',{
       responseType: "arraybuffer", // 设置响应体类型为arraybuffer
     }).then(({data})=> {
       let workbook = XLSX.read(new Uint8Array(data), {type:"array"}); // 解析数据
       var worksheet = workbook.Sheets[workbook.SheetNames[0]]; // workbook.SheetNames 下存的是该文件每个工作表名字,这里取出第一个工作表
       this.tableau = XLSX.utils.sheet_to_html(worksheet); // 渲染
     })
  }
}
</script>

三、pdf预览
1.安装依赖vue-pdf

npm install --save vue-pdf

2.在需要的页面注册

<script> 
import PDF from 'vue-pdf'
export default {
  components:{
      PDF,
  },
  data(){
      return {

      }
  }
</script>   

3.使用,一般预览pdf时都是很多页的,为了提升性能可以做个分页。page: 当前显示的页数,比如第一页page=1;rotate : 旋转角度,比如0就是不旋转,+90,-90 就是水平旋转。progress :当前页面的加载进度,范围是0-1 ,等于1的时候代表当前页已经完全加载完成了。page-loaded :页面加载成功的回调函数,不咋能用到。num-pages :总页数;error :加载错误的回调link-clicked:单机pdf内的链接会触发。print 这个是打印函数。(注意:谷歌浏览器预览时会出现乱码,这个问题是因为你pdf中使用了自定义字体导致的。若要解决须替换node_modules/vue-pdf/src/pdfjsWrapper.js,替换的pdfjsWrapper.js我放在文章最后)

    <!-- 预览PDF -->
    <el-dialog v-dialogDrag  :visible.sync="previewDialog">
      <template>
        <div>
          <div class="tools">
            <el-button :theme="'default'" type="submit" :title="'上一页'" @click.stop="prePage" class="mr10"> 上一页</el-button>
            <el-button :theme="'default'" type="submit" :title="'下一页'" @click.stop="nextPage" class="mr10"> 下一页</el-button>
            <div class="page">{{pageNum}}/{{pageTotalNum}} </div>
            <el-button :theme="'default'" type="submit" :title="'顺时针旋转'" @click.stop="clock" class="mr10"> 顺时针旋转</el-button>
            <el-button :theme="'default'" type="submit" :title="'逆时针旋转'" @click.stop="counterClock" class="mr10"> 逆时针旋转</el-button>
            <el-button :theme="'default'" type="submit" :title="'打印'" @click.stop="pdfPrintAll" class="mr10"> 打印</el-button>
          </div>
          <pdf ref="pdf" :src="url" :page="pageNum" :rotate="pageRotate" @progress="loadedRatio = $event" @page-loaded="pageLoaded($event)" 
            @num-pages="pageTotalNum=$event" @error="pdfError($event)"  @link-clicked="page = $event"></pdf>
        </div>
      </template>
    </el-dialog>
<script> 
import PDF from 'vue-pdf'
export default {
  components:{
      PDF,
  },
  data(){
      return {
          previewDialog:false,
          url: "http://storage.xuetangx.com/public_assets/xuetangx/PDF/PlayerAPI_v1.0.6.pdf",
          pageNum: 1,
          pageTotalNum: 1,
          pageRotate: 0,
          // 加载进度
          loadedRatio: 0,
          curPageNum: 0,
      },
      methods:{
    /**
     * 预览PDF
     */
    previewPDF(row,index) {
      this.previewDialog = true;
      console.log("", row,index);
      
    },
    // 上一页函数,
    prePage() {
      var page = this.pageNum
      page = page > 1 ? page - 1 : this.pageTotalNum
      this.pageNum = page
    },
    // 下一页函数
    nextPage() {
      var page = this.pageNum
      page = page < this.pageTotalNum ? page + 1 : 1
      this.pageNum = page
    },
    // 页面顺时针翻转90度。
    clock() {
      this.pageRotate += 90
    },
    // 页面逆时针翻转90度。
    counterClock() {
      this.pageRotate -= 90
    },
    // 页面加载回调函数,其中e为当前页数
    pageLoaded(e) {
      this.curPageNum = e
    },
    // 错误时回调函数。
    pdfError(error) {
      console.error(error)
    },
    // 打印全部
    pdfPrintAll() {
      /**
       * 打印界面字符乱码是因为你pdf中使用了自定义字体导致的,谷歌浏览器打印的时候预览界面真的变成了真·方块字 ,解决方案如下:
       * 用文章最后的pdfjsWrapper.js在替换掉node_modules/vue-pdf/src/pdfjsWrapper.js
       */
      console.log("打印");
      this.$refs.pdf.print()
    },

     },
  }
</script>   

4.加载本地pdf文件
如果需要加载本地pdf文件(不需要则不用配置),需要我们做一下本地配置flie-loader才行,否则webpack无法编译pdf类型的文件,配置方法也很简单,在项目根目录找到vue.config.js文件(若没有则在根目录下新建一个vue.config.js)。之后再url:require(“…/assets/xxx.pdf”)就没有任何问题了,注意,vue-pdf src接收的是string对象,如果直接传url这里报错了,需要传url.default一下。
先安装file-loader

npm install --save file-loader

然后在vue.config.js中加入以下内容:

module.exports = {
    chainWebpack: config => {
        const fileRule = config.module.rule('file')
        fileRule.uses.clear()
        fileRule
            .test(/\.pdf|ico$/)
            .use('file-loader')
            .loader('file-loader')
            .options({
                limit: 10000,
            })
    },
    publicPath: './'
}

5.解决pdf使用自定义字体预览和打印乱码问题:pdfjsWrapper.js

import { PDFLinkService } from 'pdfjs-dist/es5/web/pdf_viewer';

var pendingOperation = Promise.resolve();

export default function(PDFJS) {

    function isPDFDocumentLoadingTask(obj) {

        return typeof(obj) === 'object' && obj !== null && obj.__PDFDocumentLoadingTask === true;
        // or: return obj.constructor.name === 'PDFDocumentLoadingTask';
    }

    function createLoadingTask(src, options) {

        var source;
        if ( typeof(src) === 'string' )
            source = { url: src };
        else if ( src instanceof Uint8Array )
            source = { data: src };
        else if ( typeof(src) === 'object' && src !== null )
            source = Object.assign({}, src);
        else
            throw new TypeError('invalid src type');

        // source.verbosity = PDFJS.VerbosityLevel.INFOS;
        // source.pdfBug = true;
        // source.stopAtErrors = true;

        if ( options && options.withCredentials )
            source.withCredentials = options.withCredentials;

        var loadingTask = PDFJS.getDocument(source);
        loadingTask.__PDFDocumentLoadingTask = true; // since PDFDocumentLoadingTask is not public

        if ( options && options.onPassword )
            loadingTask.onPassword = options.onPassword;

        if ( options && options.onProgress )
            loadingTask.onProgress = options.onProgress;

        return loadingTask;
    }


    function PDFJSWrapper(canvasElt, annotationLayerElt, emitEvent) {

        var pdfDoc = null;
        var pdfPage = null;
        var pdfRender = null;
        var canceling = false;

        canvasElt.getContext('2d').save();

        function clearCanvas() {

            canvasElt.getContext('2d').clearRect(0, 0, canvasElt.width, canvasElt.height);
        }

        function clearAnnotations() {

            while ( annotationLayerElt.firstChild )
                annotationLayerElt.removeChild(annotationLayerElt.firstChild);
        }

        this.destroy = function() {

            if ( pdfDoc === null )
                return;

            // Aborts all network requests and destroys worker.
            pendingOperation = pdfDoc.destroy();
            pdfDoc = null;
        }

        this.getResolutionScale = function() {

            return canvasElt.offsetWidth / canvasElt.width;
        }

        this.printPage = function(dpi, pageNumberOnly) {

            if ( pdfPage === null )
                return;

            // 1in == 72pt
            // 1in == 96px
            var PRINT_RESOLUTION = dpi === undefined ? 150 : dpi;
            var PRINT_UNITS = PRINT_RESOLUTION / 72.0;
            var CSS_UNITS = 96.0 / 72.0;

            var printContainerElement = document.createElement('div');
            printContainerElement.setAttribute('id', 'print-container')

            function removePrintContainer() {
                printContainerElement.parentNode.removeChild(printContainerElement);
            }

            new Promise(function(resolve, reject) {
                printContainerElement.frameBorder = '0';
                printContainerElement.scrolling = 'no';
                printContainerElement.width = '0px;'
                printContainerElement.height = '0px;'
                printContainerElement.style.cssText = 'position: absolute; top: 0; left: 0';

                window.document.body.appendChild(printContainerElement);
                resolve(window)
            })
            .then(function(win) {

                win.document.title = '';

                return pdfDoc.getPage(1)
                .then(function(page) {

                    var viewport = page.getViewport({ scale: 1 });
                    printContainerElement.appendChild(win.document.createElement('style')).textContent =
                    '@supports ((size:A4) and (size:1pt 1pt)) {' +
                            '@page { margin: 1pt; size: ' + ((viewport.width * PRINT_UNITS) / CSS_UNITS) + 'pt ' + ((viewport.height * PRINT_UNITS) / CSS_UNITS) + 'pt; }' +
                        '}' +
                        '#print-canvas { display: none }' +

                        '@media print {' +
                            'body { margin: 0 }' +
                            '#print-canvas { page-break-before: avoid; page-break-after: always; page-break-inside: avoid; display: block }' +
                            'body > *:not(#print-container) { display: none; }' +
                            '}'+

                        '@media screen {' +
                            'body { margin: 0 }' +
                        '}'
                    return win;
                })
            })
            .then(function(win) {

                var allPages = [];

                for ( var pageNumber = 1; pageNumber <= pdfDoc.numPages; ++pageNumber ) {

                    if ( pageNumberOnly !== undefined && pageNumberOnly.indexOf(pageNumber) === -1 )
                        continue;

                    allPages.push(
                        pdfDoc.getPage(pageNumber)
                        .then(function(page) {

                            var viewport = page.getViewport({ scale: 1 });

                            var printCanvasElt = printContainerElement.appendChild(win.document.createElement('canvas'));
                            printCanvasElt.setAttribute('id', 'print-canvas')
                            printCanvasElt.width = (viewport.width * PRINT_UNITS);
                            printCanvasElt.height = (viewport.height * PRINT_UNITS);

                            return page.render({
                                canvasContext: printCanvasElt.getContext('2d'),
                                transform: [ // Additional transform, applied just before viewport transform.
                                    PRINT_UNITS, 0, 0,
                                    PRINT_UNITS, 0, 0
                                ],
                                viewport: viewport,
                                intent: 'print'
                            }).promise;
                        })
                    );
                }

                Promise.all(allPages)
                .then(function() {

                    win.focus(); // Required for IE
                    if (win.document.queryCommandSupported('print')) {
                        win.document.execCommand('print', false, null);
                    } else {
                        win.print();
                    }
                    removePrintContainer();
                })
                .catch(function(err) {
                    removePrintContainer();
                    emitEvent('error', err);
                })
            })
        }

        this.renderPage = function(rotate) {
            if ( pdfRender !== null ) {

                if ( canceling )
                    return;
                canceling = true;
                pdfRender.cancel().catch(function(err) {
                    emitEvent('error', err);
                });
                return;
            }

            if ( pdfPage === null )
                return;

            var pageRotate = (pdfPage.rotate === undefined ? 0 : pdfPage.rotate) + (rotate === undefined ? 0 : rotate);

            var scale = canvasElt.offsetWidth / pdfPage.getViewport({ scale: 1 }).width * (window.devicePixelRatio || 1);
            var viewport = pdfPage.getViewport({ scale: scale, rotation:pageRotate });

            emitEvent('page-size', viewport.width, viewport.height, scale);

            canvasElt.width = viewport.width;
            canvasElt.height = viewport.height;

            pdfRender = pdfPage.render({
                canvasContext: canvasElt.getContext('2d'),
                viewport: viewport
            });

            annotationLayerElt.style.visibility = 'hidden';
            clearAnnotations();

            var viewer = {
                scrollPageIntoView: function(params) {
                    emitEvent('link-clicked', params.pageNumber)
                },
            };

            var linkService = new PDFLinkService();
            linkService.setDocument(pdfDoc);
            linkService.setViewer(viewer);

            pendingOperation = pendingOperation.then(function() {

                var getAnnotationsOperation =
                pdfPage.getAnnotations({ intent: 'display' })
                .then(function(annotations) {

                    PDFJS.AnnotationLayer.render({
                        viewport: viewport.clone({ dontFlip: true }),
                        div: annotationLayerElt,
                        annotations: annotations,
                        page: pdfPage,
                        linkService: linkService,
                        renderInteractiveForms: false
                    });
                });

                var pdfRenderOperation =
                pdfRender.promise
                .then(function() {

                    annotationLayerElt.style.visibility = '';
                    canceling = false;
                    pdfRender = null;
                })
                .catch(function(err) {

                    pdfRender = null;
                    if ( err instanceof PDFJS.RenderingCancelledException ) {

                        canceling = false;
                        this.renderPage(rotate);
                        return;
                    }
                    emitEvent('error', err);
                }.bind(this))

                return Promise.all([getAnnotationsOperation, pdfRenderOperation]);
            }.bind(this));
        }


        this.forEachPage = function(pageCallback) {

            var numPages = pdfDoc.numPages;

            (function next(pageNum) {

                pdfDoc.getPage(pageNum)
                .then(pageCallback)
                .then(function() {

                    if ( ++pageNum <= numPages )
                        next(pageNum);
                })
            })(1);
        }


        this.loadPage = function(pageNumber, rotate) {

            pdfPage = null;

            if ( pdfDoc === null )
                return;

            pendingOperation = pendingOperation.then(function() {

                return pdfDoc.getPage(pageNumber);
            })
            .then(function(page) {

                pdfPage = page;
                this.renderPage(rotate);
                emitEvent('page-loaded', page.pageNumber);
            }.bind(this))
            .catch(function(err) {

                clearCanvas();
                clearAnnotations();
                emitEvent('error', err);
            });
        }

        this.loadDocument = function(src) {

            pdfDoc = null;
            pdfPage = null;

            emitEvent('num-pages', undefined);

            if ( !src ) {

                canvasElt.removeAttribute('width');
                canvasElt.removeAttribute('height');
                clearAnnotations();
                return;
            }

            // wait for pending operation ends
            pendingOperation = pendingOperation.then(function() {

                var loadingTask;
                if ( isPDFDocumentLoadingTask(src) ) {

                    if ( src.destroyed ) {

                        emitEvent('error', new Error('loadingTask has been destroyed'));
                        return
                    }

                    loadingTask = src;
                } else {

                    loadingTask = createLoadingTask(src, {
                        onPassword: function(updatePassword, reason) {

                            var reasonStr;
                            switch (reason) {
                                case PDFJS.PasswordResponses.NEED_PASSWORD:
                                    reasonStr = 'NEED_PASSWORD';
                                    break;
                                case PDFJS.PasswordResponses.INCORRECT_PASSWORD:
                                    reasonStr = 'INCORRECT_PASSWORD';
                                    break;
                            }
                            emitEvent('password', updatePassword, reasonStr);
                        },
                        onProgress: function(status) {

                            var ratio = status.loaded / status.total;
                            emitEvent('progress', Math.min(ratio, 1));
                        }
                    });
                }

                return loadingTask.promise;
            })
            .then(function(pdf) {

                pdfDoc = pdf;
                emitEvent('num-pages', pdf.numPages);
                emitEvent('loaded');
            })
            .catch(function(err) {

                clearCanvas();
                clearAnnotations();
                emitEvent('error', err);
            })
        }

        annotationLayerElt.style.transformOrigin = '0 0';
    }

    return {
        createLoadingTask: createLoadingTask,
        PDFJSWrapper: PDFJSWrapper,
    }
}

 

————————————————
版权声明:本文为CSDN博主「无月大大」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_52103939/article/details/122447620

原文地址:http://www.cnblogs.com/Im-Victor/p/16857639.html

1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长! 2. 分享目的仅供大家学习和交流,请务用于商业用途! 3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入! 4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解! 5. 如有链接无法下载、失效或广告,请联系管理员处理! 6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需! 7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员! 8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载 声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性