目录
1、背景说明
有时需要将PDF文件在浏览器上显示,并进行相应的操作。经查询此类需求可通过pdf.js插件完成。最近找了点资料,研究下了pdf.js,并实现了pdf文件的预览、打印功能
2、效果展示
具体实现的效果如图所示。
总体界面如上图所示。其中菜单标红的1、2、3分别具体的实现方式。
在翻页及打印的具体实现中,实现了翻页功能及打印功能。打印功能截图如下。
3、具体实现
3.1 环境说明
IDE:VS2019社区版
操作系统:Win10专业版
部署:IIS
架构:ASP.NET MVC5
3.2 外部资源
在实现中使用jQuery
、pdf.js
和jQuery.print.js
等。可通过github中搜索及下载相关文件。
3.3 具体实现
PDF文件可通过两种方式实现。直接使用viewer.html和使用pdf.js。其中前者特别简单。下面分别说明
3.3.1 viewer.html方式实现
3.3.1.1 具体代码
pdf下载下来后,文档结构图如图所示。
可直接通过"/MyViewPDF/Scripts/pdf/web/viewer.html?file=" + fileUrl;
实现PDF的预览及展示功能。效果如下图
具体代码如下:
(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”按钮后无法加载、无法展示,或出现如下异常
请在IIS的网站的请求筛选中,删除APP_Data配置。操作如下图所示。原因是IIS过滤掉了部分节点。
4、总结
pdf.js还是非常好用的。特别是直接使用viewer.html方式。
以上