更好的网页内嵌PDF解决方案

最近在制作作品集的时候有内嵌pdf的需求以方便在同一页面上选择pdf并浏览。但是在开发过程中遇到了很多问题,其中最棘手的就是内嵌pdf无法在webkit内核浏览器中正常显示。研究过后发现,目前主流的PDF嵌入解决方案有以下几种:

1. 浏览器原生内嵌:

  • <embed>
    <embed>可以内嵌包括application, document, img, none, presentation在内的多个 ARIA角色。当指定application及其子类型pdf时可以通过该标签实现内嵌pdf:

    <embed src="path/to/pdf" width="500" height="375" type="application/pdf">
  • <iframe>
    <iframe>本质上是在网页中内嵌另外一个页面的,其实可以实现很多进阶功能,例如实现有声音的自动播放等等。内嵌pdf的具体实现方法如下:

    <iframe src="path/to/pdf" width="500" height="375" loading="lazy" title="PDF-file" ></iframe>

然而,实际使用情况下iframe使用的更多,但是在webkit内核的浏览器上,由于自带pdf浏览器的功能局限性,在新标签页里展示的pdf仅有最基本的功能,无法实现指定页数跳转等等。同时最重要的是内嵌pdf只能浏览pdf的首页而且无法在pdf内缩放,这基本是无法使用的情况,于是

2. 第三方pdf内嵌:

pdf.js

由mozilla出品的开源 JavaScript 库,但是貌似是以canvas的形式进行渲染,还需要额外处理清晰度问题等问题。而且使用起来较为复杂。还需要自己手动配置很多额外的JS代码。优点是兼容性好,内存占用小。

Google PDF viewer

可以通过在<iframe>src属性前后分别加上https://docs.google.com/gview?url=&embedded=true的方式激活谷歌的PDF浏览器,调用的是谷歌在Google Drive上采用的那一套UI。但是问题在于仅在PC端可用,移动端显示空白。而且GFW内无法访问。

Adobe PDF Online
Adobe同谷歌一样提供包括在线字体和pdf内嵌等许多其他应用的免费使用,但是使用起来较为复杂,都需要登陆Adobe账号。

对于内嵌pdf,还需要申请API。可以在这里注册并申请。需要注意的是注册时需要填写域名,即该API下的pdf浏览器只能在指定的域名及其任何子域名。在本地测试(localhost)可以无视域名。

如上图注册完后可以拿到API KEY,复制备用。在HTML文件内添加<div id="adobe-dc-view"></div>空区块。随后需要在JS中配置文件的基本信息,具体内容如下:

<script src="https://acrobatservices.adobe.com/view-sdk/viewer.js"></script>
 <script type="text/javascript">
    document.addEventListener("adobe_dc_view_sdk.ready", function()
    {
        var adobeDCView = new AdobeDC.View({clientId: "{YOUR_CLIENT_ID}", divId: "adobe-dc-view"});
        adobeDCView.previewFile(
       {
          content:   {location: {url: "path/to/pdf"}},
          metaData: {fileName: "{filename}"}
       });
    });
 </script>

其中{YOUR_CLIENT_ID}{filename}对应刚才复制的API和文件名,后者会显示在pdf浏览器顶端。该浏览器的功能非常之多,从传统浏览器都有的页数跳转,下载打印,适应屏幕到注释,评论等进阶功能都一项不缺。

动态更新文件URI?

与常规<iframe>等原生方法通过ID锁定并更换标签内src属于不同,Adobe PDF Online要切换文件URI必须修改函数内content: location: url的值,然而函数一旦被自定义除非重新进入页面否则无法更新显示文件。此时需要在用户选择要预览的文件的链接上加上重新初始化PDF Viewer的代码,这一部分官方文档并未说明,具体操作如下:

function f(pdfurl) {
    let adobeDCView=new AdobeDC.View({clientId: "<clientID>", divId: "adobe-dc-view" });
    adobeDCView.previewFile({content: {location: {url: pdfurl}},metaData: {fileName: " "}});
}

可以看到这一部分不需要重新声明document.addEventListener(),因为监听事件第一次获取后会一直保持激活,哪怕内部函数使用有更改。最后,将函数f()注册到给用户选的的PDF文件名的onclick事件中即可。

访问作品集以查看效果展示。

已知bug:

1. 在webkit浏览器中滑动到最底部会使pdf浏览窗覆盖整个屏幕,导致某些功能失灵。

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注