微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用 pdf.js 渲染 PDF 但它不起作用,我没有收到任何错误消息来帮助我调试问题

如何解决使用 pdf.js 渲染 PDF 但它不起作用,我没有收到任何错误消息来帮助我调试问题

我正在尝试构建一个 Flask 应用程序,我可以在其中上传 pdf 文件,并在提交到后端之前进行预览。

我使用的脚本如下:

const imageUploadValidation = (function () {
  "use strict";

  pdfjsLib.GlobalWorkerOptions.workerSrc =
    "https://mozilla.github.io/pdf.js/build/pdf.js";

  const onFilePicked = function (event) {
    // Select file Nodelist containing 1 file
    const files = event.target.files;
    const filename = files[0].name;
    if (filename.lastIndexOf(".") <= 0) {
      return alert("Please add a valid file!");
    }

    const fileReader = new FileReader();

    fileReader.onload = function (e) {
      const pdfData = e.target.result;

      let loadingTask = pdfjsLib.getDocument({ data: pdfData })
      loadingTask.promise.then(function (pdf) {
          console.log("PDF loaded",pdf);

          pdf.getPage(1).then((page) => {
            console.log("page loaded",page);
            // var scale = 1.5;
            // var viewport = page.getViewport({ scale: scale });

            var iframe = document.getElementById("image-preview");
            iframe.src = page
            // var context = canvas.getContext("2d");
            // canvas.height = viewport.height;
            // canvas.width = viewport.width;

            // var renderContext = {
            //   canvasContext: context,//   viewport: viewport,// };

            // var renderTask = page.render(renderContext);
            // renderTask.promise.then(function () {
            //   console.log("Page rendered");
            // });
          });
        })
        .catch((error) => {
          console.log(error);
        });
    };
    const pdf = fileReader.readAsArrayBuffer(files[0]);
    console.log("read as Data URL",pdf);
  };

  const Constructor = function (selector) {
    const publicAPI = {};

    const changeHandler = (e) => {
      // console.log(e)
      onFilePicked(e);
    };

    publicAPI.init = function (selector) {
      // Check for errors.
      const fileInput = document.querySelector(selector);
      if (!selector || typeof selector !== "string") {
        throw new Error("Please provide a valid selector");
      }

      fileInput.addEventListener("change",changeHandler);
    };

    publicAPI.init(selector);
    return publicAPI;
  };

  return Constructor;
})();

imageUploadValidation("form input[type=file]");

加载任务承诺似乎永远不会运行。直到那一刻,一切似乎都在进行。我不熟悉这个 Promise 语法,所以我不能确定问题是否存在,或者我是如何传入 pdf 文件的。

附言注释掉的代码是我进行此设置的原始方式,什么 s uncommented 只是我测试了不同的方式。

解决方法

检查数据类型

首先,您可能想检查从 FileReader 返回的内容,特别是 pdfData 的数据类型是什么。如果您查看文档 (direct link),getDocument 需要一个 Unit8Array 或一个二进制字符串。

添加缺少的参数

您遇到的下一个问题是您在调用 getDocument 时缺少必需的参数。以下是所需的最少参数:

var args = {
    url: 'https://example.com/the-pdf-to-load.pdf',cMapUrl: "./cmaps/",cMapPacked: true,}

我从未使用 data 参数代替 url 但只要您提供正确的数据类型就可以了。请注意,cMapUrl 应该是 cmap 文件夹的相对或绝对路径。 PDFJS 通常需要这些文件来实际解释 PDF 文件。以下是演示存储库(GitHub 页面)中的所有文件:cmaps 您需要将这些文件添加到您的项目中。

我建议您将文件上传为 blob,而不是使用 data,然后您所要做的就是将 blob URL 提供为 url。我不熟悉如何做到这一点,我只知道它在现代浏览器中是可能的。

您的查看器在哪里/您不需要 iFrame 或 Canvas

PDFJS 只需要一个 div 来放置 PDF。它对一些 CSS 规则很挑剔,例如它必须绝对定位,否则 PDFJS 将页面生成为 0px 高度。

我在您的代码中没有看到 PDFViewerPDFLinkService。看起来您正在尝试自己从头开始构建整个查看器。这是不小的努力。当您使 loadingTask 正常工作时,响应应按如下方式处理:

loadingTask.promise.then(
    // Success function.
    function( doc ) {
        // viewer is holding: new pdfjsViewer.PDFViewer()
        // linkService is: new pdfjsViewer.PDFLinkService()
        viewer.setDocument( doc );
        linkService.setDocument( doc );
    },// Error function.
    function( exception ) {
        // What type of error occurred?
        if ( exception.name == 'PasswordException' ) {
            // Password missing,prompt the user and try again.
            elem.appendChild( getPdfPasswordBox() );
        } else {
            // Some other error,stop trying to load this PDF.
            console.error( exception );
        }
        /**
         * Additional exceptions can be reversed engineered from here:
         * https://github.com/mozilla/pdf.js/blob/master/examples/mobile-viewer/viewer.js
         */
    }
);

请注意,PDFViewer 会为您完成所有繁重的工作。如果您希望 PDF 中的链接起作用,则需要 PDFLinkService。您确实应该查看 live demoexample files

工作量很大,但这些 example files specifically 可以教您有关 PDFJS 的所有知识。

示例/示例代码

这是我使用 PDFJS 完成的项目中的一些示例代码。代码有点高级,但它应该可以帮助您更好地逆向工程 PDFJS 在幕后的工作方式。

pdfObj = 一个对象,用于存储此 PDF 文件的所有信息和对象。我在一个页面上加载了多个 PDF,所以我需要这样来保持它们彼此分开。

updatePageInfo = 我的自定义函数,当用户更改 PDF 中的页面时,由 PDFJS 的 eventBus 调用;当他们从一页滚动到另一页时会发生这种情况。

pdfjsViewer.DownloadManager = 我允许用户下载 PDF,所以我需要使用它。

pdfjsViewer.EventBus = 处理 PDF 的加载、页面更改等事件。我不是 100% 肯定,但我认为 PDFViewer 需要这样做。

pdfjsViewer.PDFViewer = 什么处理实际向用户显示您的 PDF。 container 是页面上要呈现的元素,记住它必须绝对定位。

// Create a new PDF object for this PDF.
var pdfObj = {
    'container': elem.querySelector('.pdf-view-wrapper'),'document': null,'download': new pdfjsViewer.DownloadManager(),'eventBus': new pdfjsViewer.EventBus(),'history': null,'id': id,'linkService': null,'loaded': 0,'loader': null,'pageTotal': 0,'src': elem.dataset.pdf,'timeoutCount': 0,'viewer': null
};

// Update the eventBus to dispatch page change events to our own function.
pdfObj.eventBus.on( 'pagechanging',function pagechange(evt) { 
    updatePageInfo( evt );
} );

// Create and attach the PDFLinkService that handles links and navigation in the viewer.
var linkService = new pdfjsViewer.PDFLinkService( {
    'eventBus': pdfObj.eventBus,'externalLinkEnabled': true,'externalLinkRel': 'noopener noreferrer nofollow','externalLinkTarget': 2 // Blank
} );
pdfObj.linkService = linkService;

// Create the actual PDFViewer that shows the PDF to the user.
var pdfViewer = new pdfjsViewer.PDFViewer(
    {
        'container': pdfObj.container,'enableScripting': false,// Block embeded scripts for security
        'enableWebGL': true,'eventBus': pdfObj.eventBus,'linkService': pdfObj.linkService,'renderInteractiveForms': true,// Allow form fields to be editable
        'textLayerMode': 2
    }
);
pdfObj.viewer = pdfViewer;
pdfObj.linkService.setViewer( pdfObj.viewer );

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。