「PDF.js」如何在网页中嵌入PDF文件

作为一名准牛马研究生,我经常需要在博客中记录一些常用的算法,不免需要在个人网页插入PDF格式的文档或指南以辅助说明。所以本文就像借这个机会水一篇文章对比几种常见的在网页中插入PDF文件的方法。主要包括iframe标签、Object标签、embed标签、smallPDF工具以及最重要的PDF.js。

iframe标签

iframe标签是最容易想到的一种在网页上插入PDF文件的方法。通常情况下,iframe用于在网页中嵌入另一个网页。随着现代浏览器对PDF文件的支持越来越好,利用iframe标签嵌入PDF进行展示也越来越稳定了。想要利用iframe标签嵌入PDF也非常简单,只需要一行HTML代码即可:

1
<iframe src="https://img.astrophel.top/202502081705706.pdf" width="100%" height="600px"></iframe>

这种方法嵌入的PDF会利用浏览器自带的PDF阅读工具显示出来,非常简便。但问题是许多奇奇怪怪的浏览器(如微信自带的浏览器)很容易出现显示错误,且对于大型PDF文件加载耗时较长。

Object标签

object标签用于包含对象,也是现代浏览器支持的一个常用HTML标签。其作用就是在网页中插入各种对象,最早是为了取代img元素而诞生的。不过因为其存在漏洞,该目的最终也并未达成。object的使用也很简单,如下所示:

1
<object data="https://img.astrophel.top/202502081705706.pdf" type="application/pdf" width="100%" height="600px"></object>

该方法与利用iframe标签插入并无太多区别,主要缺点是object标签存在漏洞且在HTML 5中已接近淘汰、不同浏览器会用不同的方式加载同样的对象,且容易出现PDF文件在网页加载时直接被下载的情况。

embed标签

embed标签是HTML 5中新出现的一种标签,其定义了一个容器,用来嵌入外部应用或者互动程序。其使用方法与以上两个标签相似,也只需要一行HTML代码即可:

1
<embed src="https://img.astrophel.top/202502081705706.pdf" type="application/pdf" width="100%" height="600px">

尴尬的是,embed标签在老旧浏览器中并不支持,同时现行标准也已不推荐使用embed标签,而是建议使用 img、iframe、video等标签代替。此外在一些浏览器中加载embed标签中的PDF依赖于第三方插件,无法直接在浏览器中渲染。

smallPDF

smallPDF是一个比较知名的在线PDF工具,其中一个在线工具就提供了将PDF嵌入网站的功能:


与以上三种方法不同,它引入了外部的服务对PDF文件进行渲染,不再调用用户本地的程序,可以确保在不同设备上实现相同或相似的显示效果,能够实现更好的兼容性。它的使用方法也并不复杂,只需要打开以上页面,输入PDF文件的URL,在点击生成代码,粘贴到自己的网页上即可。

smallPDF工具页面
生成的代码如下所示:

1
<div style="width: 100%; height: 600px;" class="smallpdf-widget" data-pdf-url="https://img.astrophel.top/202502081705706.pdf"></div><script src="https://smallpdf.com/api/embed-widget.js"></script>

我们来看一下显示效果:

相比以上方案,smallPDF提供了一种完成度较高的PDF嵌入方式,但是它提供的这个页面绝对称不上好用——无法选中PDF中的文字,文件清晰度变差,最重要的是左下角总是带着它的广告链接。同时博主对这个网站的印象并不好

如果既想让用户在不同终端获得相似的使用体验,又能提供方便的阅读工具,那么就必须要请出本文的主角:PDF.js了。

PDF.js

PDF.js是Mozilla开发的一个用于在Web中解析和呈现PDF的开源工具,在GitHub上有进50k stars。其实质上就是Firefox中自带的PDF阅读器,几乎在大部分支持显示PDF文件的网站上都能看到它的身影。PDF.js具有极其优秀的性能,能够秒开大型PDF文件,几乎不会耽误网页的加载速度;同时高度可定义化,能够设置不同的权限,允许或限制用户复制、打印、下载等。其唯一的缺点就是部署相对以上方法更复杂。其实也不复杂

部署过程

首先,访问PDF.js的官网或GitHub页面:


打开Releases页面,选择一个预构建版本。为了稳定性,这里不推荐下载最新版本,而是用上一个大版本的最后一个小版本。通常这个版本是Bug最少,完成度最高的。本文以v3.11.174版本为例展示部署过程。
在Assets中下载自己选好的版本,如pdfjs-3.11.174-dist.zip,解压可以看到其中包含两个文件夹:buildwebbuild中存放运行PDF.js所必须的依赖程序,web界面则存储项目的前端页面。其中viewer.html就是我们显示PDF时打开的页面。双击viewer.html,在浏览器中显示一片空白,这是因为PDF.js必须在网页服务器上通过HTTP/HTTPS协议被访问。
接下来,把pdfjs整个文件夹中的内容上传至服务器,通过URL访问viewer.html(本文中为https://www.astrophel.top/pdf/web/viewer.html),可以看到项目自带的示例PDF成功加载在浏览器中了。

PDF.js默认页面
但是如果我们想要加载自己的PDF文件该怎么办呢?很简单,添加链接后缀?file=your-file-link(本文中为https://www.astrophel.top/pdf/web/viewer.html?file=https://img.astrophel.top/202502081705706.pdf)即可。
如果你需要加载的PDF文件域名与PDF.js的部署域名是相同的,那么到此PDF.js就部署完成了。但如果二者位于不同的域名下,那么访问这个链接会发现页面竟然又变成空白的了。按F12打开浏览器控制台,发现错误信息指示存在跨域问题
由于本博客几乎所有媒体资源都存储在腾讯云的对象存储中,所以我必须要解决跨域问题才能正常使用PDF.js。下面将介绍如何解决该问题。

跨域问题的解决

跨域指的是一个网站的页面不能执行其他网站的脚本,这是由浏览器的同源策略造成的,是浏览器对javascript施加的安全限制。PDF.js解决跨域问题,要从两个方面着手:首先是PDF.js自身的跨域限制,其次是PDF资源本身的跨域限制。

要避免PDF.js自身的跨域限制,需要修改其源码:在其web文件夹下打开viewer.js文件,搜索file origin does not match viewer’s,将这一行代码注释掉,然后重新上传到服务器中。这样就解除了PDF.js自身的跨域限制。
修改PDF.js代码
如果你使用的文件来自自己的服务器,那么到此PDF.js就部署完成了。但如果你使用了诸如腾讯云COS这样的对象存储服务,那么还需要修改PDF资源本身的跨域限制。

以腾讯云COS为例,打开腾讯云控制台,找到“对象存储”,在存储桶安全管理选项卡中找到“跨域访问 CORS 设置”,点击添加规则,允许自己PDF.js部署站点的域名对COS存储桶进行跨域访问。
COS跨域访问设置
如果你的存储桶像我一样使用了CDN加速,还需要到CDN设置中,点击域名管理,选择对象存储的加速域名,打开“高级配置“,在“HTTP响应头配置”中添加与存储桶中相同的“Access-Control-Allow-Origin”设置并启动。
CDN跨域设置
这样,PDF.js就能正常显示跨域的PDF文件资源了。
加载跨域PDF示例图
现在,我们只需要用iframe标签将这个网页嵌入到我们的页面上即可:

1
<iframe src="https://www.astrophel.top/pdf/web/viewer.html?file=https://img.astrophel.top/202502081705706.pdf" width="100%" height="600px"></iframe>