pdfjs-dist web预览pdf文件, pdfjs-dist example

11,376 阅读3分钟

背景:需要使用web显示pdf文件

技术栈:vue2.x vue-cli3.x+

大坑1:使用vue-pdf

  1. 分页加载,大文件加载,比如加载一个300M的pdf直接崩溃,报错
  2. github官网运行不起来

大坑2:直接使用pdfjs-dist

基于vue-pdf不符合需求,看了看看vue-pdf源码,什么玩意,封装的组件都看不明白,而且还有bug

pdfjs-dist没有vue example,看了半天其他的文档,官网的文档也写的贼烂。。。

直接使用报下面错误

> pdfjs-dist@0.1.0 serve
> vue-cli-service serve 

 INFO  Starting development server...
98% after emitting CopyPlugin

 ERROR  Failed to compile with 3 errors                                                                                                                                                                                                         00:29:54
 error  in ./node_modules/pdfjs-dist/build/pdf.js

Module parse failed: Unexpected character '#' (1387:9)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
|
| class PDFDocumentLoadingTask {
>   static #docId = 0;
|
|   constructor() {

 @ ./node_modules/cache-loader/dist/cjs.js??ref--13-0!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--1-0!./node_modules/vue-loader/lib??vue-loader-options!./src/App.vue?vue&type=script&lang=js& 12:0-39 16:0-28 27:19-39 84:28-48
 @ ./src/App.vue?vue&type=script&lang=js&
 @ ./src/App.vue
 @ ./src/main.js
 @ multi (webpack)-dev-server/client?http://192.168.1.6:8080&sockPath=/sockjs-node (webpack)/hot/dev-server.js ./src/main.js

 error  in ./node_modules/pdfjs-dist/build/pdf.sandbox.js

Module parse failed: Unexpected token (162:47)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
|         return this.exportValueToSandbox(result);
|       } catch (error) {
>         throw this.createErrorForSandbox(error?.toString() ?? "");
|       }
|     };

 @ ./node_modules/cache-loader/dist/cjs.js??ref--13-0!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--1-0!./node_modules/vue-loader/lib??vue-loader-options!./src/App.vue?vue&type=script&lang=js& 15:0-64 44:35-47       
 @ ./src/App.vue?vue&type=script&lang=js&
 @ ./src/App.vue
 @ ./src/main.js
 @ multi (webpack)-dev-server/client?http://192.168.1.6:8080&sockPath=/sockjs-node (webpack)/hot/dev-server.js ./src/main.js

 error  in ./node_modules/pdfjs-dist/web/pdf_viewer.js

Module parse failed: Unexpected token (342:37)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
|
| function fixupLangCode(langCode) {
>   return PARTIAL_LANG_CODES[langCode?.toLowerCase()] || langCode;
| }
|

 @ ./node_modules/cache-loader/dist/cjs.js??ref--13-0!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--1-0!./node_modules/vue-loader/lib??vue-loader-options!./src/App.vue?vue&type=script&lang=js& 13:0-57 27:44-65 46:29-49 48:35-61 52:38-67 57:40-71 61:30-51
 @ ./src/App.vue?vue&type=script&lang=js&
 @ ./src/App.vue
 @ ./src/main.js
 @ multi (webpack)-dev-server/client?http://192.168.1.6:8080&sockPath=/sockjs-node (webpack)/hot/dev-server.js ./src/main.js

原因: vue-cli babel-loader默认不重新打包node_modules里面的模块

解决办法:vue.config.js 导出的配置中添加 transpileDependencies: ['pdfjs-dist']即可,具体往下看有详细解析

大坑3:使用pdfjs-dist的legacy

在低版本的chrome部分pdf文件没有被解析出来,报错不支持


好吧,慢慢看看


下面给能用的写法,网上好多都不可以使用

安装模块 pdfjs-dist

pdf.js npm 版本就是 pdfjs-dist

目前最新文档的版本是 pdfjs-dist@2.14.305

npm install pdfjs-dist@2.14.305

配置vue.config.js 这不一定不能落下,不然直接报错,不解析语法

默认vue-cli忽略node_modules

vue.config.js

module.exports = {
    // 默认情况下 babel-loader 会忽略所有 node_modules 中的文件。你可以启用本选项,以避免构建后的代码中出现未转译的第三方依赖。
    // 不过,对所有的依赖都进行转译可能会降低构建速度。如果对构建性能有所顾虑,你可以只转译部分特定的依赖:给本选项传一个数组,列出需要转译的第三方包包名或正则表达式即可。
    transpileDependencies: ['pdfjs-dist']
};

编写vue组件,完整代码如下

<template>
    <div id="app">
        <div id="pageContainer" style="position: absolute">
            <div id="viewer"></div>
        </div>
    </div>
</template>

<script>
import "pdfjs-dist/web/pdf_viewer.css";
import * as pdfjsLib from "pdfjs-dist";
import * as pdfjsViewer from "pdfjs-dist/web/pdf_viewer";
import "pdfjs-dist/build/pdf.worker.entry";
import * as pdfjsSandbox from "pdfjs-dist/build/pdf.sandbox.js";

pdfjsLib.GlobalWorkerOptions.workerSrc = window.pdfjsWorker;

export default {
    name: "App",
    components: {},
    async mounted() {
        if (!pdfjsLib.getDocument || !pdfjsViewer.PDFViewer) {
            // eslint-disable-next-line no-alert
            alert(
                "Please build the pdfjs-dist library using\n  `gulp dist-install`"
            );
        }

        // Some PDFs need external cmaps.
        // const CMAP_URL = './cmaps/';
        const CMAP_URL = "./cmaps/";
        const CMAP_PACKED = true;

        const DEFAULT_URL = "./compressed.tracemonkey-pldi-09.pdf";
        // To test the AcroForm and/or scripting functionality, try e.g. this file:
        // "../../test/pdfs/160F-2019.pdf"

        const ENABLE_XFA = true;
        const SEARCH_FOR = ""; // try "Mozilla";

        // const SANDBOX_BUNDLE_SRC =
        //     '../../node_modules/pdfjs-dist/build/pdf.sandbox.js';
        const SANDBOX_BUNDLE_SRC = pdfjsSandbox;

        const container = document.getElementById("pageContainer");

        const eventBus = new pdfjsViewer.EventBus();

        // (Optionally) enable hyperlinks within PDF files.
        const pdfLinkService = new pdfjsViewer.PDFLinkService({
            eventBus,
        });

        // (Optionally) enable find controller.
        const pdfFindController = new pdfjsViewer.PDFFindController({
            eventBus,
            linkService: pdfLinkService,
        });

        // (Optionally) enable scripting support.
        const pdfScriptingManager = new pdfjsViewer.PDFScriptingManager({
            eventBus,
            sandboxBundleSrc: SANDBOX_BUNDLE_SRC,
        });

        const pdfViewer = new pdfjsViewer.PDFViewer({
            container,
            eventBus,
            linkService: pdfLinkService,
            findController: pdfFindController,
            scriptingManager: pdfScriptingManager,
            enableScripting: true, // Only necessary in PDF.js version 2.10.377 and below.
        });
        pdfLinkService.setViewer(pdfViewer);
        pdfScriptingManager.setViewer(pdfViewer);

        eventBus.on("pagesinit", function () {
            // We can use pdfViewer now, e.g. let's change default scale.
            pdfViewer.currentScaleValue = "page-width";

            // We can try searching for things.
            if (SEARCH_FOR) {
                eventBus.dispatch("find", { type: "", query: SEARCH_FOR });
            }
        });

        // Loading document.
        const loadingTask = pdfjsLib.getDocument({
            url: DEFAULT_URL,
            cMapUrl: CMAP_URL,
            cMapPacked: CMAP_PACKED,
            enableXfa: ENABLE_XFA,
        });
        const pdfDocument = await loadingTask.promise;
        // Document loaded, specifying document for the viewer and
        // the (optional) linkService.
        pdfViewer.setDocument(pdfDocument);

        pdfLinkService.setDocument(pdfDocument, null);
    },
};
</script>

<style>
#pageContainer {
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
}
#pageContainer .page {
    position: relative;
    border: 1px solid black;
    margin-bottom: 20px;
    overflow: hidden;
    box-sizing: border-box;
}
</style>


可以看到效果了