目录

  • 1、背景说明
  • 2、效果展示
  • 3、具体实现
  • 3.1 环境说明
  • 3.2 外部资源
  • 3.3 具体实现
  • 3.3.1 viewer.html方式实现
  • 3.3.1.1 具体代码
  • 3.3.1.2 viewer.html源码
  • 3.3.2 pdf.js实现
  • 3.3.2.1 具体代码
  • 3.3.2.2 源码解读
  • 3.4 免费源码
  • 3.5 其他说明
  • 4、总结


1、背景说明

有时需要将PDF文件在浏览器上显示,并进行相应的操作。经查询此类需求可通过pdf.js插件完成。最近找了点资料,研究下了pdf.js,并实现了pdf文件的预览、打印功能

2、效果展示

具体实现的效果如图所示。

jquery 移动端pdfjs预览 js实现pdf预览功能_c#


总体界面如上图所示。其中菜单标红的1、2、3分别具体的实现方式。

jquery 移动端pdfjs预览 js实现pdf预览功能_jquery 移动端pdfjs预览_02


在翻页及打印的具体实现中,实现了翻页功能及打印功能。打印功能截图如下。

jquery 移动端pdfjs预览 js实现pdf预览功能_jquery 移动端pdfjs预览_03

3、具体实现

3.1 环境说明

IDE:VS2019社区版
操作系统:Win10专业版
部署:IIS
架构:ASP.NET MVC5

3.2 外部资源

在实现中使用jQuerypdf.jsjQuery.print.js等。可通过github中搜索及下载相关文件。

3.3 具体实现

PDF文件可通过两种方式实现。直接使用viewer.html和使用pdf.js。其中前者特别简单。下面分别说明

3.3.1 viewer.html方式实现

3.3.1.1 具体代码

pdf下载下来后,文档结构图如图所示。

jquery 移动端pdfjs预览 js实现pdf预览功能_jquery 移动端pdfjs预览_04


可直接通过"/MyViewPDF/Scripts/pdf/web/viewer.html?file=" + fileUrl;实现PDF的预览及展示功能。效果如下图

jquery 移动端pdfjs预览 js实现pdf预览功能_jquery 移动端pdfjs预览_05


具体代码如下:

(1)html中的代码如下:

<h2 id="mytitle">通过View.html的Url加载PDF</h2>
<button id="loadBtn">加载</button>

<iframe id="showpdfframe" src="" style="height:400px;width:100%"></iframe>

(2)js端的代码

//加载PDF按钮
    $("#loadBtn").click(
        function () {

            //获取路径(需要根据实际业务场景,获取文件的路径)
            var fileUrl = encodeURIComponent("/MyViewPDF/App_Data/test.pdf");

            //整合路径
            var url = "/MyViewPDF/Scripts/pdf/web/viewer.html?file=" + fileUrl;

            //展示
            $("#showpdfframe").attr("src", url);
        }
    );

通过在自己的界面中iframe标签,将viewer.html加载到其中,实现PDF的预览及各项功能

3.3.1.2 viewer.html源码

通过viewer.js的初始化方法webViewerInitialized定义如下:

function webViewerInitialized() {
  var appConfig = PDFViewerApplication.appConfig;
  var file;
  var queryString = document.location.search.substring(1);
  var params = (0, _ui_utils.parseQueryString)(queryString);
  file = "file" in params ? params.file : _app_options.AppOptions.get("defaultUrl"); //这句是重点*******
  validateFileURL(file);
  var fileInput = document.createElement("input");
  fileInput.id = appConfig.openFileInputName;
  fileInput.className = "fileInput";
  fileInput.setAttribute("type", "file");
  fileInput.oncontextmenu = _ui_utils.noContextMenuHandler;
  document.body.appendChild(fileInput);

在方法中,有一句话很重要。file = "file" in params ? params.file : _app_options.AppOptions.get("defaultUrl");这句话对传入的参数进行了判断。其查看传入的URL中是否包含file参数的请求内容。例如:http://localhost/MyViewPDF/ViewPDF/Index/viewer.html?file=test.pdf。此请求就包含了file参数。若包含了file参数,则使用file参数,若没有,则使用defaultUrl。而defaultUrl在viewer.html中的定义为:

defaultUrl: {
    value: "compressed.tracemonkey-pldi-09.pdf",
    kind: OptionKind.VIEWER
  },

所以在网上其他例子中,有些人是用URL后面跟file参数,有些是通过对defaultUrl参数重新赋值实现。

3.3.2 pdf.js实现

另外一种方式是通过pdf.js实现。具体过程如下

3.3.2.1 具体代码

前端html代码如下

<h4>加载PDF指定页面</h4>
<p><button id="loadPdfBtn">加载PDF文件</button></p>
<p>
    <canvas id="the-canvas" style="border: 1px solid black; direction: ltr;"></canvas>
</p>

前端的js代码如下

//加载PDF按钮
    $("#loadPdfBtn").click(
        function () {

            //发起ajax请求,请求获取PDF的文件流
            $.ajax({
                async: false,
                type: 'POST',
                url: "/MyViewPDF/ViewPDF/getPdfStream",
                data: {
                    "args": "" //可带参数请求
                },
                success: function (rJson) {
                    var rObj = $.parseJSON(rJson);
                    if (rObj.success === "true") { 

                        var pdfData = atob(rObj.data);
                        pdfjsLib.GlobalWorkerOptions.workerSrc = '/MyViewPDF/Scripts/pdf/build/pdf.worker.js';//自己的路径

                        var loadingTask = pdfjsLib.getDocument({
                            data: pdfData
                        }); 

                        loadingTask.promise.then(function (pdf) {
                            //加载指定界面(第一页)
                            pdf.getPage(1).then(function (page) {
                                var scale = 1.2;
                                var viewport = page.getViewport({ scale: scale });
                                var canvas = document.getElementById('the-canvas');
                                var context = canvas.getContext('2d');
                                canvas.height = viewport.height;
                                canvas.width = viewport.width;
                                var renderContext = {
                                    canvasContext: context,
                                    viewport: viewport,
                                };
                                page.render(renderContext);
                            });
                        });

                    } else {
                        alert(rObj.message);
                    }
                }
            }); //ajax结束
        }
    );

实现思路:将后台的PDF文件转为文件流,pdf.js收到文件流后,将文件流传给画布(canvas)标签。通过canvas标签展示内容。

3.3.2.2 源码解读

以上js代码中有一个方法:pdfjsLib.getDocument。这个方法很重要。在上面的代码中,是将

{
	data: pdfData
}

作为参数,传给了getDocument方法,但getDocument方法,不仅仅可以接受这一种参数。还可以接受其他类型的参数。其在pdf.js中的源码如下:

function getDocument(src) {
  var task = new PDFDocumentLoadingTask();
  var source;

  if (typeof src === "string") { //第一种参数
    source = {
      url: src
    };
  } else if ((0, _util.isArrayBuffer)(src)) {  //第二种参数
    source = {
      data: src
    };
  } else if (src instanceof PDFDataRangeTransport) { //第三种参数
    source = {
      range: src
    };
  } 
	...  //省略部分代码
  }

也就说getDocument可以接受多种类型的参数,因此大家可能在网上找到的其他资料,参数会不同,有些用url、有些用data的

3.4 免费源码

以上全部源码,下载地址为:下载地址 提取码:NHZL

3.5 其他说明

若运行工程代码后,点击“URL加载PDF”按钮后无法加载、无法展示,或出现如下异常

jquery 移动端pdfjs预览 js实现pdf预览功能_c#_06


请在IIS的网站的请求筛选中,删除APP_Data配置。操作如下图所示。原因是IIS过滤掉了部分节点。

jquery 移动端pdfjs预览 js实现pdf预览功能_html_07


jquery 移动端pdfjs预览 js实现pdf预览功能_c#_08

4、总结

pdf.js还是非常好用的。特别是直接使用viewer.html方式。
以上