专注于 JetBrains IDEA 全家桶,永久激活,教程
持续更新 PyCharm,IDEA,WebStorm,PhpStorm,DataGrip,RubyMine,CLion,AppCode 永久激活教程

vue-pdf查看pdf文件及打印乱码问题处理

前言

vue中简单使用vue-pdf预览pdf文件,解决打印预览乱码问题

vue-pdf 使用

安装

npm install --save vue-pdf

引入

import pdf from "vue-pdf

自定义封装pdf预览组件

<template>
  <el-dialog
    :visible.sync="pdfDialog"
    :close-on-click-modal="false"
    :show-close="false"
    width="900px"
    top="52px"
  >
    <div class="pdf" v-show="fileType == 'pdf'">
      <p class="arrow">
        <!-- 上一页 -->
        <span
          @click="changePdfPage(0)"
          class="currentPage"
          :class="{ grey: currentPage == 1 }"
          >上一页  </span
        >
        <span style="color: #8c8e92;">{{ currentPage }} / {{ pageCount }}</span>
        <!-- 下一页 -->
        <span
          @click="changePdfPage(1)"
          class="currentPage"
          :class="{ grey: currentPage == pageCount }"
          >  下一页</span
        >    <button @click="$refs.pdf.print()">下载</button>

        <span
          style="float :right;padding-right:40px;font-size: 20px;color: #8c8e92;cursor: pointer;"
          @click="close"
          ><i class="el-icon-close"></i
        ></span>
      </p>
      <!-- loadPdfHandler:加载事件 src:需要展示的PDF地址;currentPage:当前展示的PDF页码;pageCount=$event:PDF文件总页码;currentPage=$event:一开始加载的页面-->
      <pdf
         ref="pdf"
        :src="src"
        :page="currentPage"
        @num-pages="pageCount = $event"
        @page-loaded="currentPage = $event"
        @loaded="loadPdfHandler"
      ></pdf>
    </div>
  </el-dialog>
</template>

<script>
import pdf from "vue-pdf";
export default {
  components: { pdf },
  props: ["src"],
  data() {
    return {
      filesProps: {
        label: "originName"
      },
      pdfDialog: false,
      currentPage: 0, // pdf文件页码
      pageCount: 0, // pdf文件总页数
      fileType: "pdf" // 文件类型
    };
  },
  methods: {
    // 改变PDF页码,val传过来区分上一页下一页的值,0上一页,1下一页
    changePdfPage(val) {
      if (val === 0 && this.currentPage > 1) {
        this.currentPage--;
      }
      if (val === 1 && this.currentPage < this.pageCount) {
        this.currentPage++;
      }
    },
    // pdf加载时
    loadPdfHandler() {
      this.currentPage = 1; // 加载的时候先加载第一页
    },
    handleOpen() {
      this.pdfDialog = true;
    },
    //关闭弹框
    close() {
      this.pdfDialog = false;
    }
  }
};
</script>

<style lang="stylus">
.currentPage {
    cursor: pointer;
    color: #8c8e92;
}

.currentPage:hover {
    color: #2761ff;
}
.arrow{
    position: fixed;
    top: 0px;
    left :0px;
    z-index: 2;
    width: 100%;
    background-color: #191919;
    padding: 12px 0;
    margin: 0;
    text-align :center;
}
>>>.el-dialog__body {
    color: #606266;
    font-size: 14px;
    padding:0;
}
</style>

使用

<template>
  <el-container>
    <el-header>
      <el-card>
        <div>
          <el-button
            style="font-style:oblique;font-size: 18px;"
            @click="handlePreviewFile"
            >PDF 预览</el-button
          >
          <el-button
            style="float: right;line-height: 40px;padding: 3px;"
            type="text"
            @click="handleSafetyExperience"
            ><i class="el-icon-caret-left">返回</i></el-button
          >
        </div>
      </el-card>
    </el-header>
    <el-main>
      <el-card class="card-style">
        <pdf-preview ref="pdfSearch" :src="src"></pdf-preview>
      </el-card>
    </el-main>
  </el-container>
</template>

<script>
import PdfPreview from "../widget/PdfPreview";
export default {
  name: "InfoExperience",
  components: {
    PdfPreview
  },
  data() {
    return {
      src:
        "http://storage.xuetangx.com/public_assets/xuetangx/PDF/PlayerAPI_v1.0.6.pdf"
    };
  },
  created() {},
  methods: {
    handlePreviewFile() {
      this.$refs.pdfSearch.handleOpen();
    },
    handleSafetyExperience() {
      this.$router.push({ path: "/safetyApp/sharedExperience" });
    }
  }
};
</script>

<style scoped></style>

预览效果

82_1.png

点击下载打印预览

预览出现乱码

82_2.png

pdf打印乱码解决办法

打开vue-pdf插件目录node_modules/vue-pdf/src/pdfjsWrapper.js

82_3.png

解决办法

详见Github上提供解决办法 Fix fonts issue in printing #130

乱码解决,打印预览正常

82_4.png

修改后pdfjsWrapper.js源码

以下为本人修改的pdfjsWrapper.js文件,亲测解决乱码问题

import { PDFLinkService } from 'pdfjs-dist/lib/web/pdf_link_service';

export default function(PDFJS) {

    function isPDFDocumentLoadingTask(obj) {

        return typeof(obj) === 'object' && obj !== null && obj.__PDFDocumentLoadingTask === true;
    }

    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');

        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;
            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 iframeElt = document.createElement('iframe');
            var printContainerElement = document.createElement('div');
            printContainerElement.setAttribute('id', 'print-container')

            // function removeIframe() {
            //
            //  iframeElt.parentNode.removeChild(iframeElt);
            function removePrintContainer() {
                printContainerElement.parentNode.removeChild(printContainerElement);

            }

            new Promise(function(resolve, reject) {

                // iframeElt.frameBorder = '0';
                // iframeElt.scrolling = 'no';
                // iframeElt.width = '0px;'
                // iframeElt.height = '0px;'
                // iframeElt.style.cssText = 'position: absolute; top: 0; left: 0';
                //
                // iframeElt.onload = function() {
                //
                //  resolve(this.contentWindow);
                // }
                //
                // window.document.body.appendChild(iframeElt);
                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(1);
                    // win.document.head.appendChild(win.document.createElement('style')).textContent =
                    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 }' +
                            'canvas { page-break-before: avoid; page-break-after: always; page-break-inside: avoid }' +
                        '#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(1);

                            // var printCanvasElt = win.document.body.appendChild(win.document.createElement('canvas'));
                            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();
                      }
                    // removeIframe();
                    removePrintContainer();
                })
                .catch(function(err) {

                    // removeIframe();
                    removePrintContainer();
                    emitEvent('error', err);
                })
            })
        }

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

                if ( canceling )
                    return;
                canceling = true;
                pdfRender.cancel();
                return;
            }

            if ( pdfPage === null )
                return;

            if ( rotate === undefined )
                rotate = pdfPage.rotate;

            var scale = canvasElt.offsetWidth / pdfPage.getViewport(1).width * (window.devicePixelRatio || 1);
            var viewport = pdfPage.getViewport(scale, rotate);

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

            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);

            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
                });
            });

            pdfRender
            .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))
        }

        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;

            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;
            }

            if ( isPDFDocumentLoadingTask(src) ) {

                if ( src.destroyed ) {

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

                var loadingTask = src;
            } else {

                var 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));
                    }
                });
            }

            loadingTask
            .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,
    }
}

文章永久链接:https://tech.souyunku.com/44138

未经允许不得转载:搜云库技术团队 » vue-pdf查看pdf文件及打印乱码问题处理

JetBrains 全家桶,激活、破解、教程

提供 JetBrains 全家桶激活码、注册码、破解补丁下载及详细激活教程,支持 IntelliJ IDEA、PyCharm、WebStorm 等工具的永久激活。无论是破解教程,还是最新激活码,均可免费获得,帮助开发者解决常见激活问题,确保轻松破解并快速使用 JetBrains 软件。获取免费的破解补丁和激活码,快速解决激活难题,全面覆盖 2024/2025 版本!

联系我们联系我们