PDF.JS在线预览pdf出现Failed to fetch错误和跨域问题

新手上路,请多包涵

我在Vue项目中使用pdf.js希望实现在线预览pdf文件,利用pdf.js中的viewer.html打开pdf文件时,先是出现网上常有的

file origin does not match viewer’s

错误,在注释掉源文件中的代码后

  // if (origin !== viewerOrigin && protocol !== 'blob:') {
  //   throw new Error('file origin does not match viewer\'s');
  // }

又出现了

Uncaught (in promise) Error: 载入 PDF 时发生错误。

Failed to fetch错误,并且加载pdf地址时出现了跨域错误

clipboard.png

请问这是服务器处理pdf文件出现的问题吗?应该怎么解决?

阅读 32.1k
4 个回答

服务端添加CORS相关跨域头,这种建议在nginx层,不要下沉到业务

要彻底解决 PDF.js 的跨域问题,让 PDF.js 可以从 url 加载文档,需要解决 PDF.js 本身和浏览器的双重跨域问题。

以下修改的Demo和源码:https://demos.libertynlp.com/...
源码是我已经完成所有跨域设置的 PDF.js 代码,下载后导入你的项目中即可从 url 动态加载pdf。

1.1 禁用PDF.js跨域

要禁用 PDF.js CORS,需要在 viewer.js 文档中将下面一段代码注释掉,让它失效。这一步你已经做了,继续做剩下的步骤

// 原代码
      if (origin !== viewerOrigin && protocol !== "blob:") {
        throw new Error("file origin does not match viewer's");
      }

// 注释掉上方代码
      // if (origin !== viewerOrigin && protocol !== "blob:") {
      //   throw new Error("file origin does not match viewer's");
      // }

1.2 绕过浏览器跨域

要解决浏览器 URL 文件跨域的问题,可以通过后端服务器将PDF 文件转换成流文件的方式返回给 PDF.js,不过这里我们不讨论这样的策略,而是讨论如何只在前端解决这个问题。按照以下步骤可以解决问题。

  1. 在 viewer.js 中注释掉以下三处代码

    // inactivate follow original code in viewer.js
    
    //first place
    function webViewerLoad() {
     var config = getViewerConfiguration();
     window.PDFViewerApplication = pdfjsWebApp.PDFViewerApplication;
     window.PDFViewerApplicationOptions = pdfjsWebAppOptions.AppOptions;
     var event = document.createEvent("CustomEvent");
     event.initCustomEvent("webviewerloaded", true, true, {});
     document.dispatchEvent(event);
     pdfjsWebApp.PDFViewerApplication.run(config);
    }
    
    //second place
    if (document.readyState === "interactive" || document.readyState === "complete") {
     webViewerLoad();
    } else {
     document.addEventListener("DOMContentLoaded", webViewerLoad, true);
    }
    
    //third place
    run: function run(config) {
     this.initialize(config).then(webViewerInitialized);
    },
  2. 重写 webViewerLoad 和 run 函数

    // 重写 webViewerLoad 函数
    window.webViewerLoad = function webViewerLoad(fileUrl) {
     var config = getViewerConfiguration();
     window.PDFViewerApplication = pdfjsWebApp.PDFViewerApplication;
     window.PDFViewerApplicationOptions = pdfjsWebAppOptions.AppOptions;
     var event = document.createEvent('CustomEvent');
     event.initCustomEvent('webviewerloaded', true, true, {});
     document.dispatchEvent(event);
    
     if (fileUrl) {
         config.defaultUrl = fileUrl;
     }
     pdfjsWebApp.PDFViewerApplication.run(config);
    }
    
    //rewrite run function
    //modeify for browser CORS
    run: function run(config) {
     var _that = this;
     //add judgement
     if (config.defaultUrl) {
         _app_options.AppOptions.set('defaultUrl', config.defaultUrl)
     }
    
     _that.initialize(config).then(function() {
         webViewerInitialized()
     });
    },

1.3 调用以上修改

在 viewer.html 中新增一个函数,目的是在加载页面时调用修改过的 webViewerLoad 函数。

< script type = "text/javascript" >
    window.onload = function() {
        var pdfUrl = "https://heritagesciencejournal.springeropen.com/track/pdf/10.1186/s40494-021-00620-2.pdf";
        webViewerLoad(pdfUrl);
    }
</script>

2. 从URL动态加载PDF

修改 viewer.html 中的函数,根据 viewer.html 所在 iframe 标签 src 中携带的 PDF url 加载文件。

<script type = "text/javascript" >
    window.onload = function() {
        var all_href = location.href;
        var file_id = all_href.split('?')[1];
        var pdfUrl = file_id.split('=')[1];
        // var pdfUrl='https://fireflycos.libertynlp.com/firefly-static/new_shouce.pdf';
        webViewerLoad(pdfUrl);
    }
</script>
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题