<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Webview加載pdf遇到的一些坑及解決方法

          共 1735字,需瀏覽 4分鐘

           ·

          2021-11-09 22:14

          大廠技術(shù)??高級前端??Node進(jìn)階

          點(diǎn)擊上方?程序員成長指北,關(guān)注公眾號

          回復(fù)1,加入高級Node交流群


          問題來源

          問題一切的來源還是得從那天說起...

          有一天產(chǎn)品小王拿著電腦興致勃勃的來到我的工位旁:“誒,小付,這里有個(gè)在線pdf預(yù)覽的功能,你看下能不能做。”

          聽完我心中暗想:這還不簡單,加載在線pdf不就和加載網(wǎng)頁一樣的,webview加上pdf鏈接,搞定!

          這一想完,立即比了個(gè)OK:“沒問題,簡單!”

          說完立馬開干,新建項(xiàng)目,準(zhǔn)備好webview,pdf鏈接,webView?.loadUrl("https://www.gjtool.cn/pdfh5/git.pdf"),點(diǎn)擊Run,滿心歡喜等待pdf加載出來的那一刻。

          咦?怎么一片空白,難道是webview設(shè)置項(xiàng)有問題,但是加載網(wǎng)頁一點(diǎn)問題都沒啊。這時(shí)候瞥見隔壁iOS老大哥已經(jīng)成功加載出pdf了,一問也是用webview加載的,那為啥擱我這就不行?看不起我?

          帶著疑惑查了下。

          原來Android的webview壓根就不支持加載pdf。

          Android與iOS不同,iOS加載pdf,不管本地還是在線,直接使用webview渲染就可以了,而Android卻做不到。

          那該怎樣去加載pdf?

          加載的方案有很多,比如直接跳到第三方瀏覽器加載,但產(chǎn)品要求只能在app內(nèi)部預(yù)覽,pass;比如在pdf鏈接前加上谷歌服務(wù),但在國內(nèi)是無法訪問的,pass;比如下載后再進(jìn)行加載,但當(dāng)pdf體積大且網(wǎng)絡(luò)不好時(shí),下載就會出現(xiàn)問題,又pass;

          方式有多種,第三方的輪子也有很多,但適合自己的開發(fā)需求,以及滿足UI設(shè)計(jì),則就需要進(jìn)行二次改造了。

          經(jīng)過多方對比,使用webview加載pdf的方案更符合大多數(shù)的場景。

          以下就會從webview加載pdf的方案出發(fā),描述在開發(fā)時(shí)所涉及到的問題點(diǎn)。

          我的爬坑之旅開始了!

          初步加載

          webview加載pdf的初步設(shè)想是使用js的方式去渲染,

          新建一個(gè)js

          var?url?=?location.search.substring(1);

          PDFJS.cMapUrl?=?'https://unpkg.com/[email protected]/cmaps/';
          PDFJS.cMapPacked?=?true;

          var?pdfDoc?=?null;

          function?createPage()?{
          ????var?div?=?document.createElement("canvas");
          ????document.body.appendChild(div);
          ????return?div;
          }

          function?renderPage(num)?{
          ????pdfDoc.getPage(num).then(function?(page)?{
          ????????var?viewport?=?page.getViewport(2.0);
          ????????var?canvas?=?createPage();
          ????????var?ctx?=?canvas.getContext('2d');

          ????????canvas.height?=?viewport.height;
          ????????canvas.width?=?viewport.width;

          ????????page.render({
          ????????????canvasContext:?ctx,
          ????????????viewport:?viewport
          ????????});
          ????});
          }

          PDFJS.getDocument(url).then(function?(pdf)?{
          ????pdfDoc?=?pdf;
          ????for?(var?i?=?1;?i?<=?pdfDoc.numPages;?i++)?{
          ????????renderPage(i)
          ????}
          });

          新建Html

          "en">

          ????"UTF-8">
          ????"viewport"
          ??????????content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=4.0,user-scalable=no"/>
          ????Document
          ????type="text/css">
          ????????canvas?{
          ????????????width:?100%;
          ????????????height:?100%;
          ????????????border:?1px?solid?black;
          ????????}
          ????
          ????
          ????




          準(zhǔn)備好js和html后,使用webview對在線pdf(www.gjtool.cn/pdfh5/git.p…[1] 進(jìn)行加載,

          webView?.loadUrl("file:///android_asset/index.html?https://www.gjtool.cn/pdfh5/git.pdf");

          運(yùn)行成功后,pdf也加載出來了。

          添加雙指縮放

          好家伙,終于是加載出了pdf,我滿心歡喜的拿著效果給產(chǎn)品看一看。

          “你這是加載出來了,但是字體看著有點(diǎn)小,你看能不能加上雙指縮放的功能”。產(chǎn)品小王看了一眼,

          “那必須能啊。”

          將webview設(shè)置為支持縮放狀態(tài),并且useWideViewPort設(shè)置為true,讓W(xué)ebivew支持meta標(biāo)簽的viewport屬性,

          settings?.useWideViewPort?=?true
          settings?.builtInZoomControls?=?true
          settings?.setSupportZoom(true)
          settings?.displayZoomControls?=?false?//不顯示縮放按鈕

          并且修改html中的meta屬性,設(shè)置minimum-scalemaximum-scale屬性,以及將user-scalable置為yes

          運(yùn)行成功后,成功對pdf進(jìn)行雙指縮放。

          產(chǎn)品看了過后,點(diǎn)了點(diǎn)頭。我也開開心心的提交了代碼。

          簽章無法顯示

          以為這個(gè)小功能已經(jīng)開發(fā)完成,沒有多大的問題,直到有一天測試小姐姐找到我,

          “你這pdf顯示有問題,當(dāng)pdf上有簽章時(shí),簽章無法顯示”

          “what?”

          簽章無法顯示,這個(gè)倒是沒有自測過,趕緊找測試要了鏈接來驗(yàn)證,經(jīng)過驗(yàn)證,簽章的顯示確實(shí)有問題。所謂簽章,即在pdf上加蓋公章或者簽名。如下圖

          (來源網(wǎng)絡(luò))

          簽章是屬于后期添加在pdf上,對于簽章的加載,簡單的js是無法加載成功的。

          那該如何處理?

          其實(shí)有個(gè)非常強(qiáng)大的第三方庫pdf.js[2]已經(jīng)幫我們處理好了,pdf.js可通過pdf文件的地址或pdf數(shù)據(jù)流獲取pdf,具體實(shí)現(xiàn)是調(diào)用接口函數(shù) PDFJs.getDocument(url/buffer)將pdf載入html,通過canvas處理, 然后渲染pdf文件,當(dāng)然也能夠顯示出簽章。

          只不過它的使用有點(diǎn)麻煩,需要先將pdf.js下載出來,下載地址[3] ,copy到Android項(xiàng)目中assert文件夾中,

          最后加載方式還是和上方一樣使用webview來加載。缺點(diǎn)就是包體積增大。

          當(dāng)我們使用pdf.js默認(rèn)加載pdf時(shí),會發(fā)現(xiàn)效果圖的上方出現(xiàn)了多余的控制按鈕,比如下圖:

          但是在UI設(shè)計(jì)圖中,是沒有包含這些控制按鈕的,如果就這么提交,估計(jì)不一會UI小姐姐就來找我了。

          那該如何處理?

          其實(shí)在本篇一開始使用的方式中,加載完成pdf是沒有這些控制按鈕的,那么問題來了,我們是不是可以將第一種方式與pdf.js相結(jié)合,來進(jìn)行加載?

          pdf.js主要包含兩個(gè)核心庫文件,一個(gè)pdf.js和一個(gè)pdf.worker.js,一個(gè)負(fù)責(zé)API解析,一個(gè)負(fù)責(zé)核心解析。如果需要與第一種方式結(jié)合,我們就將pdf.jspdf.worker.js以及pdf.sandbox.js三個(gè)文件copy出來,放到assert中。

          在html中的script標(biāo)簽中添加對pdf.jspdf.worker.js等的引用,





          修改index.js文件

          var?url?=?location.search.substring(1);

          function?createPage()?{
          ????var?div?=?document.createElement("canvas");
          ????document.body.appendChild(div);
          ????return?div;
          }

          alert(url);

          function?renderPage(num)?{
          ????pdfDoc.getPage(num).then(function?(page)?{
          ????????var?viewport?=?page.getViewport({?scale:?2.0?});
          ????????var?canvas?=?createPage();
          ????????var?ctx?=?canvas.getContext('2d');

          ????????canvas.height?=?viewport.height;
          ????????canvas.width?=?viewport.width;

          ????????page.render({
          ????????????canvasContext:?ctx,
          ????????????viewport:?viewport
          ????????}).promise.then(()?=>?{});
          ????});
          }

          pdfjsLib.getDocument(url).promise.then(function?(pdf)?{
          ????pdfDoc?=?pdf;
          ????for?(var?i?=?1;?i?<=?pdfDoc.numPages;?i++)?{
          ????????renderPage(i)
          ????}
          });

          可以看到運(yùn)行成功后,簽章成功展示且多余的控制按鈕也不會顯示,這里效果圖就不展示了。

          我又開開心心的提交了代碼。

          中文字符顯示不全

          又過了一段時(shí)間,我正愉快的敲著代碼,這時(shí)候測試小姐姐又找到了我,

          “這邊pdf顯示有點(diǎn)問題,一些文字、字符顯示不全,出現(xiàn)缺少字符的現(xiàn)象”

          “what?”

          我趕緊重現(xiàn)驗(yàn)證下,當(dāng)pdf上有多種字體時(shí),會有概率出現(xiàn)字符顯示不全的現(xiàn)象。查了查,當(dāng)運(yùn)行加載此類pdf時(shí),在控制臺上會出現(xiàn)了一些警告信息。

          “Error during font loading”

          是因?yàn)樵诮馕鰌df時(shí),默認(rèn)的字體庫已經(jīng)不能覆蓋多種字體,也就無法將所有字體顯示完全。

          那如何處理?

          默認(rèn)字體庫無法滿足,那就添加新的字體庫,

          在pdf.js文件中添加cMapUrl = "cdn.jsdelivr.net/npm/pdfjs-d…[4]" ,

          params.rangeChunkSize?=?params.rangeChunkSize?||?DEFAULT_RANGE_CHUNK_SIZE;
          params.CMapReaderFactory?=?params.CMapReaderFactory?||?DefaultCMapReaderFactory;
          params.ignoreErrors?=?params.stopAtErrors?!==?true;
          params.fontExtraProperties?=?params.fontExtraProperties?===?true;
          params.pdfBug?=?params.pdfBug?===?true;
          params.enableXfa?=?params.enableXfa?===?true;
          params.cMapPacked?=?true
          params.cMapUrl?=?"https://cdn.jsdelivr.net/npm/[email protected]/cmaps/"

          ok,運(yùn)行看看,中文已顯示完全。

          以上,webview加載pdf的問題基本已經(jīng)解決。針對webview加載pdf的方案,主要解決問題如下:

          • 雙指縮放;
          • 簽章無法顯示;
          • 存在多余控制按鈕;
          • 中文字符顯示不全。

          這幾個(gè)是加載pdf中最主要的問題,其他的小問題都好解決。

          全部代碼已放置在github:pdf-webview[5]

          關(guān)于本文

          作者:付十一?

          https://juejin.cn/post/7017840637450043422

          參考資料

          [1]

          https://www.gjtool.cn/pdfh5/git.pdf%EF%BC%89

          [2]

          https://github.com/mozilla/pdf.js

          [3]

          https://mozilla.github.io/pdf.js/

          [4]

          https://cdn.jsdelivr.net/npm/[email protected]/cmaps/

          [5]

          https://github.com/fuusy/PdfWebview



          Node 社群



          我組建了一個(gè)氛圍特別好的 Node.js 社群,里面有很多 Node.js小伙伴,如果你對Node.js學(xué)習(xí)感興趣的話(后續(xù)有計(jì)劃也可以),我們可以一起進(jìn)行Node.js相關(guān)的交流、學(xué)習(xí)、共建。下方加 考拉 好友回復(fù)「Node」即可。


          ???“分享、點(diǎn)贊在看” 支持一波??

          瀏覽 203
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  狠狠伊人久久 | 国产亚洲中文字幕 | 亚洲色情直播 | 天天操天天舔 | 精品自在线 |