这两天有个需求,要在网页上显示PDF文件。首先< object >、< embed >、< iframe >这几个标签就能实现PDF文件的预览(无需JavaScript支持),我还在网上看了下发现挺多第三方js库可以实现PDF预览,如jQuery Document Viewer、jquery.media.js、PDFObject、PDF.js等等。我大概看了下PDFObject、PDF.js这两个库,前者并不是一个PDF的渲染工具,而是通过使用< embed >标签来显示PDF;后者则会解析PDF文件内容,还能将PDF渲染成Canvas。

< iframe >

所有浏览器都支持 < iframe > 标签,直接将src设置为指定的PDF文件就可以预览了。此外可以把需要的文本放置在 < iframe > 和 之间,这样就可以应对无法理解 iframe 的浏览器,比如下面的代码可以提供一个PDF的下载链接:

<iframe src="/index.pdf" width="100%" height="100%">This browser does not support PDFs. Please download the PDF to view it: <a href="/index.pdf">Download PDF</a></iframe>

< embed >

< embed > 标签定义嵌入的内容,比如插件。在HTML5中这个标签有4个属性:

属性 描述
height pixels 设置嵌入内容的高度。
width pixels 设置嵌入内容的宽度。
type type 定义嵌入内容的类型。
src url 嵌入内容的 URL。

但是需要注意的是这个标签不能提供回退方案,与< iframe > < / iframe >
不同,这个标签是自闭合的的,也就是说如果浏览器不支持PDF的嵌入,那么这个标签的内容什么都看不到。用法如下:

<embed src="/index.pdf" type="application/pdf" width="100%" height="100%">

< object >

< object >定义一个嵌入的对象,请使用此元素向页面添加多媒体。此元素允许您规定插入 HTML 文档中的对象的数据和参数,以及可用来显示和操作数据的代码。用于包含对象,比如图像、音频、视频、Java applets、ActiveX、PDF 以及 Flash。几乎所有主流浏览器都拥有部分对 < object > 标签的支持。这个标签在这里的用法和< iframe >很小,也支持回退:

<object data="/index.php" type="application/pdf" width="100%" height="100%">This browser does not support PDFs. Please download the PDF to view it: <a href="/index.pdf">Download PDF</a></object>

当然,结合< object >和< iframe >能提供一个更强大的回退方案:

<object data="/index.pdf" type="application/pdf" width="100%" height="100%"><iframe src="/index.pdf" width="100%" height="100%" style="border: none;">This browser does not support PDFs. Please download the PDF to view it: <a href="/index.pdf">Download PDF</a></iframe></object>

以上三个标签是一种无需JavaScript支持的PDF预览方案。下面提到的PDFObject和PDF.js都是js库。

PDFObject

看官网上的介绍,PDFObject并不是一个PDF渲染工具,它也是通过< embed >标签实现PDF预览:

PDFObject is not a rendering engine. PDFObject just writes an < embed > element to the page, and relies on the browser or browser plugins to render the PDF. If the browser does not support embedded PDFs, PDFObject is not capable of forcing the browser to render the PDF.

PDFObject提供了一个PDFObject.supportsPDFs用于判断该浏览器能否使用PDFObject:

if(PDFObject.supportsPDFs){console.log("Yay, this browser supports inline PDFs.");
} else {console.log("Boo, inline PDFs are not supported by this browser");
}

整个PDFObject使用起来非常简单,完整代码:

<!DOCTYPE html>
<html>
<head><title>Show PDF</title><meta charset="utf-8" /><script type="text/javascript" src='pdfobject.min.js'></script><style type="text/css">html,body,#pdf_viewer{width:100%;height:100%;margin:0;padding:0;}</style>
</head>
<body><div id="pdf_viewer"></div>
</body>
<script type="text/javascript">if(PDFObject.supportsPDFs){// PDF嵌入到网页PDFObject.embed("index.pdf", "#pdf_viewer" );} else {location.href = "/canvas";}</script>
</html>

效果如下:

PDF.js

PDF.js可以实现在html下直接浏览pdf文档,是一款开源的pdf文档读取解析插件,非常强大,能将PDF文件渲染成Canvas。PDF.js主要包含两个库文件,一个pdf.js和一个pdf.worker.js,一个负责API解析,一个负责核心解析。
首先引入pdf.js文件<script type="text/javascript" src='pdf.js'></script>
PDF.js大部分用法都是基于Promise的,PDFJS.getDocument(url)方法返回的就是一个Promise:

    PDFJS.getDocument('../index.pdf').then(pdf=>{var numPages = pdf.numPages;var start = 1;renderPageAsync(pdf, numPages, start);});

Promise返回的pdf是一个PDFDocumentProxy对象官网API介绍是:

Proxy to a PDFDocument in the worker thread. Also, contains commonly used properties that can be read synchronously.

PDF的解析工作需要通过pdf.getPage(page)去执行,这个方法返回的也是一个Promise,因此可以通过async/await函数去逐页解析PDF:

    async function renderPageAsync(pdf, numPages, current){for(let i=1; i<=numPages; i++){// 解析pagelet page = await pdf.getPage(i);// 渲染// ...}}

得到的page是一个PDFPageProxy对象,即Proxy to a PDFPage in the worker thread 。这个对象得到了这一页的PDF解析结果,我们可以看下这个对象提供的方法:

方法 返回
getAnnotations A promise that is resolved with an {Array} of the annotation objects.
getTextContent That is resolved a TextContent object that represent the page text content.
getViewport Contains ‘width’ and ‘height’ properties along with transforms required for rendering.
render An object that contains the promise, which is resolved when the page finishes rendering.

我们可以试试调用getTextContent方法,并将其结果打印出来:

page.getTextContent().then(v=>console.log('page', v));

第一页部分结果如下:

{"items": [{"str": "小册子标题","dir": "ltr","width": 240,"height": 2304,"transform": [48,0,0,48,45.32495,679.04],"fontName": "g_d0_f1"},{"str": " ","dir": "ltr","width": 9.600000000000001,"height": 2304,"transform": [48,0,0,48,285.325,679.04],"fontName": "g_d0_f2"}],"styles": {"g_d0_f1": {"fontFamily": "monospace","ascent": 1.05810546875,"descent": -0.26171875,"vertical": false},"g_d0_f2": {"fontFamily": "sans-serif","ascent": 0.74365234375,"descent": -0.25634765625}}}

我们可以发现,PDF.js将每页文本的字符串、位置、字体都解析出来,感觉还是挺厉害的。

官网有个demo,还用到了官网提到的viewer.js(我认为它的作用是对PDF.js渲染结果再次处理):http://mozilla.github.io/pdf.js/web/viewer.html,我看了一下它的HTML机构,首先底图是一个Canvas,内容和PDF一样(通过下面介绍的page.render方法可以得到),底图之上是一个textLayer,我猜想这一层就是通过page.getTextContent()得到了字体的位置和样式,再覆盖在Canvas上:

通过这种方式就能实现再预览文件上选中文字(刚开始我还在纳闷为什么渲染成Canvas还能选择文字)

将page渲染成Canvas是通过render方法实现的,代码如下:

    async function renderPageAsync(pdf, numPages, current){console.log("renderPage async");for(let i=1; i<=numPages; i++){// pagelet page = await pdf.getPage(i);let scale = 1.5;let viewport = page.getViewport(scale);// Prepare canvas using PDF page dimensions.let canvas = document.createElement("canvas");let context = canvas.getContext('2d');document.body.appendChild(canvas);canvas.height = viewport.height;canvas.width = viewport.width;// Render PDF page into canvas context.let renderContext = {canvasContext: context,viewport: viewport};page.render(renderContext);}}

PDF.js是Mozilla实验室的作品,感觉真的很强大!
我在码云上有个demo,结合了PDFObject和PDF.js。因为PDFObject使用的< embed >标签可以直接显示PDF文件,速度很快;但是手机上很多浏览器不支持,比如微信的浏览器、小米浏览器,所以我就使用了PDF.js将其渲染成Canvas,速度与PDFObject相比慢多了,但至少能看。-_-||
demo地址:https://git.oschina.net/liuyaqi/PDFViewer.git

参考:
PDFObject:https://pdfobject.com
PDF.js: http://mozilla.github.io/pdf.js/

前端预览PDF:PDFObject、PDF.js相关推荐

  1. vue项目实现前端预览word和pdf格式文件

    最近做vue项目遇到一个需求,就是前端实现上传word或pdf文件后,后端返回文件对应的文件流,前端需要在页面上展示出来.word预览简单一些,pdf预览我试过pdfjs,vue-pdf总是报各种奇奇 ...

  2. 不使用前端的pdf.js,通过pdfbox转换pdf为图片,拼接成html实现pdf前端预览

    一般情况,pdf类型的文件在前端预览,都是通过前端插件,或者获取源文件浏览器自带的工具预览,由于项目中,是前后端分离,前端不想使用pdf.js类的插件,预览的要求又是只能看不能下载,所以只能另外想别的 ...

  3. PDF、Word、Excel文件前端预览实操干货都在这!

    随着Odoo在各个行业领域的深入应用,对Odoo的前端交互体验要求也越来越高. 我们在项目开发中常常会遇到,需要上传文件并预览的问题. 这里是我遇到的需求,并完成的一个小demo. 在Odoo中实现文 ...

  4. 前端预览 PDF 文件几种方式汇总(使用PDFJS)

    哈喽大家好啊.前半年还挺忙的,一直也没有发文章,有老哥想我了嘛.这两天发现老有人私信问我 PDF 相关的内容. 那么好,为了我能安心摸鱼,我准备出一篇文章来介绍一下如何使用 PDFJS . PDF.j ...

  5. 前端在线预览word,excel,pdf

    前端在线预览word,excel,pdf 预览Word 预览pdf 预览Excel 预览Word 微软的在线预览功能,可以预览word.ppt.Excel.PDF 局限: 需要外网能访问文件,如果是只 ...

  6. html 打印预览 兼容,vue下使用 pdf.js 预览 和 打印 PDF文档 兼容React

    我使用前端开发框架是vue,有一个打印PDF文档的需求. 这个需求最开始是交给后台,但是明显不切实际, 因为后台服务器,根本就无法连接打印机. 所以这个预览加打印文档的需求就交到了前端, 开始我有想过 ...

  7. vue下使用 pdf.js 预览 和 打印 PDF文档 兼容React

    我使用前端开发框架是vue,有一个打印PDF文档的需求. 这个需求最开始是交给后台,但是明显不切实际, 因为后台服务器,根本就无法连接打印机. 所以这个预览加打印文档的需求就交到了前端, 开始我有想过 ...

  8. php+预览和下载pdf文件,vue实现在线预览pdf文件和下载(pdf.js)

    最近做项目遇到在线预览和下载pdf文件,试了多种pdf插件,例如jquery.media.js(ie无法直接浏览) 最后选择了pdf.js插件(兼容ie10及以上.谷歌.安卓,苹果) 强烈推荐改插件, ...

  9. 【vue2】纯前端实现本地的pdf/word/epub文件预览(包括pdf选中文字,epub高亮等)

    前言 需求是预览本地的pdf/word/epub格式的文件,但是搜索后发现没有可以直接使用的,格式不同,显示的方式和效果也都略有不同. 最后还是分别实现预览的功能. 补充功能:pdf选中文字,epub ...

  10. (开源kkFileView、kkOffice)在线预览word、pdf、ofd、excel、ppt、压缩包、图片等等

    (开源kkFileView.kkOffice)在线预览word.pdf.ofd.excel.ppt.压缩包.图片等 前言 此项目为文件文档在线预览项目解决方案,对标业内付费产品有[永中office][ ...

最新文章

  1. 构造函数 – WebSocket
  2. mongoDB研究笔记:分片集群的工作机制
  3. Ubuntu14.04 kylin 安装配置Tomcat7服务器
  4. android contacts 编辑,如何在Android中的.csv文件中逐行编写contactn...
  5. python 40位的数减个位数_Python数据分析入门教程(五):数据运算
  6. java not a jpeg file_javax.imageio.IIOException: Not a JPEG file: starts with 0x47 0x49
  7. pulsar配置文件常用配置项
  8. 限时,字节Java程序性能优化宝典大全,这才叫真正的性能优化
  9. 松下服务器报警13参数修改,新版松下伺服发生故障报警代码一览及对策.doc
  10. Loongson2_龙芯灵珑9S2A_usb或硬盘方式安装debian6 [刘工版]
  11. NEFU ERP 企业资源计划[1] 详细知识点
  12. 阿里测试左移和开发赋能分享
  13. 综合训练(考勤系统)
  14. Visio日程规划图——论文计划进度图
  15. 微信小程序学习之路——浮动与定位
  16. 阿里云南京云栖大会举行 给制造业升级下猛药
  17. 基于STM32温室大棚监测系统Protues仿真设计温湿度采集光照
  18. 用css的变换绘制银河系
  19. Anduino+esp8266_relay继电器 开发智能开关,APP可远程控制
  20. AI深度学习入门与实战15 TensorBoard:实验统计分析助手

热门文章

  1. vue + 高德地图 + 图例
  2. Android美化插件,KWGT桌面插件美化
  3. comsol通直流电_COMSOL 在电力行业中的 10 种实际用途
  4. python3 pyv8 linux,Python 3.4不能安装Pyv8模块
  5. 【机器学习】(七)马尔可夫链、马尔可夫随机场、条件随机场
  6. ES6 阮一峰阅读学习
  7. Python实现中英文翻译方法总结
  8. java 创建线程的三种方式、创建线程池的四种方式
  9. Halcon教程四:一个小技巧
  10. OpenPose的使用