1. 程式人生 > >前端預覽PDF:PDFObject、PDF.js

前端預覽PDF:PDFObject、PDF.js

這兩天有個需求,要在網頁上顯示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++){
            // 解析page
            let 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++){
            // page
            let 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

相關推薦

前端PDFPDFObjectPDF.js

這兩天有個需求,要在網頁上顯示PDF檔案。首先< object >、< embed >、< iframe >這幾個標籤就能實現PDF檔案的預覽(無需JavaScript支援),我還在網上看了下發現挺多第三方js庫可以實現PDF

線上WORD文件,PDF文件

在網上找了很多資料,發現這方面的資料不多,也不是很完整,以下是我整理的一些東西,希望能給大家有幫助 1.所用工具:FlashPaper,FlashPaper是一個虛擬印表機,可將word檔案轉化成swf格式檔案(.doc .xls .txt .pdf等檔案都可以正常生成SWF格式),既然轉換成SWF了,就知

Android實現線上office文件(Word,Pdf,excel,PPT.txt等格式)

1.概述 我們都知道,Android原生並沒有提供瀏覽office文件格式的相關Api,在安卓端想要實現線上預覽office文件的功能顯然很是複雜,我們手機安裝QQ瀏覽器時,在手機開啟office文件時會提示如圖, 這就是這篇文章的主角–騰訊X5核心(T

使用pdf.js線上遠端伺服器上的pdf檔案

在網上找的例子大多都是線上預覽本地pdf檔案,但是如果地址直接指向伺服器地址,則會出現跨域問題,無法正常獲取預覽檔案........ 我的解決思路就是將遠端檔案轉換成檔案流,然後將pdf.js的檔案地址指向獲取檔案流的地址,下附程式碼....................

java實現線上--poi實現wordexcelppt轉html

分享一下我的偶像大神的人工智慧教程!http://blog.csdn.net/jiangjunshow 也歡迎轉載我的文章,轉載請註明出處 https://blog.csdn.net/aabbyyz java實現線上預覽 - -之poi實現word、e

JS:上傳時圖片(inputtype="file" :)

  一、準備工作 1.預設素材:Img_add.png 2 使用window.FileReader :預覽 二、以預設圖片覆蓋input:type="file"元素。瀏覽圖片,實現預覽  <!doctype html> <html> <he

利用HTML5上傳檔案並顯示在前端,以圖片為例

由於專案中有上傳檔案的功能,所以這次單獨拿出來研究研究,我上網查了查,以前都是用iframe,但是自從HTML5出世之後,就可以利用H5的一些特性來上傳檔案了,啥也不說了,我上程式碼了 <!DOCTYPE html> <html lang

前端input上傳的圖片

既然要實現在前端預覽上傳的圖片,我們需要先了解input 和 file型別 Input 標籤的file型別,提供了上傳檔案的功能,通過此型別,可以上傳檔案到伺服器。 input的file型別,在上傳檔案時,會返回一個File物件,這個物件會存在一個FileList數組裡邊

上傳圖片截圖控制元件不顯示cropper.js 跨域問題

上傳圖片到圖片伺服器,因為域名不同,多以會有跨域問題。 No ‘Access-Control-Allow-Origin’ header is present on the requested resource. Origin ‘http://img.xxx.com’ is there

移動端圖片外掛-fly-zomm-img.min.js

移動端圖片預覽外掛,一個JQ的外掛,支援手勢放大縮小;有點小bug,不過感覺是可以接受的; 使用很簡單: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <

HTTPS配置入門NginxNode.js配置HTTPS伺服器

申請數字證書 首先需要申請一個免費的數字證書,前提是有個域名,申請起來還是很方便的。例如可以在騰訊雲申請:https://www.qcloud.com/product/ssl,具體申請步驟請參考騰訊雲文件,本文不再詳細介紹。當然還有收費的數字證書,土豪隨意。

前端面試之模組化-3require.js的用法

原文連結:http://www.ruanyifeng.com/blog/2012/11/require_js.html 一、為什麼要用require.js? 最早的時候,所有Javascript程式碼都寫在一個檔案裡面,只要載入這一個檔案就夠了。後來,程式碼越來越多,一個檔

Electron學習一ElectronNode.jsJavaScriptJQueryVue.jsAngular.js的不同

結論 這些技術,成就JavaScript大法,全面實現JavaScript語言在Web、桌面、移動、伺服器等領域應用。 JavaScript是一種指令碼程式語言,常用在瀏覽器前端頁面動態效

前端實現線上pdfwordxlsppt等檔案

1、前端實現pdf檔案線上預覽功能 方式一: 通過a標籤href屬性實現 pdf檔案理論上可以在瀏覽器直接開啟預覽但是需要開啟新頁面。在僅僅是預覽pdf檔案且UI要求不高的情況下可以直接通過a標籤href屬性實現預覽 <a href="文件地址"></

Asp.net MVC 利用(aspose+pdfobject.js) 實現線上wordexcelpptpdf檔案

線上預覽word、excel、ppt利用aspose動態生成html 主要程式碼 private bool OfficeDocumentToHtml(string sourceDoc, string saveDoc) { bool result = false;

PDFPDFObject.js總結

this pdf閱讀器 -c containe link 用戶 維度 打開 輕松 get from:PDF預覽之PDFObject.js總結 PDFObject.js - 將PDF嵌入到一個div內,而不是占據整個頁面(要求瀏覽器支持顯示PDF,不支

PDFWORDEXCELPPT

** PDF、WORD、EXCEL、PPT預覽 ** 前臺頁面 獲取fileType(檔案型別)、key(檔案id)、title(檔案標題)、url(檔案路徑)、documentType(不同的檔案格式對應的值不同,後臺程式碼中會有,傳到前臺即可)5個值到頁面即

txtdocxlspptpdf檔案線上

txt、doc、xls、ppt、pdf檔案預覽   實現思路: android通過第三方API對映附件網路地址對附件進行線上預覽。 ios通過iframe對附件設定src進行線上預覽。 document.addEventListener( "plusready", fu

h5線上doxxlspptpdf

h5線上預覽dox、xls、ppt、pdf        App中上傳附件的伺服器後,需要對附件進行預覽; webApp可以通過兩種方式實現, 1、將附件下載到本地,通過plus.runtime.openFile開啟本地檔案 2、

【微信小程式】下載並文件——pdfwordexcel等多種型別

簡要:wx.downloadFile(OBJECT)下載檔案資源到本地,客戶端直接發起一個 HTTP GET 請求,返回檔案的本地臨時路徑。wx.openDocument(OBJECT)新開頁面開啟文件,支援格式:doc, xls, ppt, pdf, docx, xlsx, pptx。 呼