1. 程式人生 > >FlowPaper中文PDF亂碼的一種解決辦法

FlowPaper中文PDF亂碼的一種解決辦法

view r.js 完全 pdf 配置 -a 比對 html framwork

[關鍵詞]FlowPaper、PDF.js、亂碼

[結論]先給出解決辦法,後面的大段內容只是為了記錄當時的排查過程。

PDF.js有全局變量對象PDFJS(1.8以上版本在pdf.js最後,1.5.x的版本沒找到,在代碼取值地方設置也可,下有說明),可以設置字體資源路徑和方式(關於字體資源的說明可看此貼https://stackoverflow.com/questions/32764773/what-is-a-pdf-bcmap-file),如果采用默認不設置就可能會出現找不到資源文件亂碼的情況,可根據自己項目路徑寫定配置路徑即可。

背景:


需要對PDF進行在線展示,為了能夠操作編輯不選擇swf格式,而是將PDF轉為HTML5,用到了FlowPaper(免費版)。

大部分PDF沒有問題,但少量PDF出現了中文亂碼情況,如下圖所示:

中文都不顯示,或顯示為方塊

圖1:

技術分享

圖2:

技術分享

由於FlowPaper底層PDF to HTML用的也是開源組件PDF.js(https://mozilla.github.io/pdf.js/),在PDF.js官方demo上測試,本來亂碼的PDF是正常的,先排除了PDF本身問題(其實PDF文本也可能有原因,內置字體、版本號等,但是由於有不亂碼的情況,先忽略),開始進行排查。

排查:


首先懷疑是版本問題,FlowPaper內置的是1.5.x的PDF.js,PDF.js官網最新版是1.8.xx,在線測試確實無問題,遂考慮覆蓋FlowPaper內的PDF.js(FlowPaper的js壓縮過,文件名改為pdf.min.js和pdf.worker.min.js)。

這裏說明一下,PDF.js官網下載到的發行版zip包括兩個文件夾[build]和[web],其中web內是演示程序,build內是核心js文件,兩個文件夾一起放到tomcat下訪問web/viewer.html即可上傳PDF測試功能了。

直接替換後,FlowPaer運行正常,英文和一些中文pdf可以正常顯示,說明核心功能沒變化,開源的東西主要就怕版本叠代後兼容性不好,測試會亂碼的pdf,在開發工具控制臺可以看到如下錯誤:

技術分享

有點眉目,這個鏈接是不存在的肯定請求不到,檢查對應的js代碼,發現null是url的變量,GBK-EUC-H就是字體資源文件夾下的一個文件,感覺有戲,遂想到用偷懶的辦法,在這裏手工指定url和字體資源cmaps文件夾路徑,讓它請求到正確的地址不就好了……

驗證確實有效,雖然沒搞明白機制,但是項目裏這個路徑肯定是不變的,能用就好了,還要忙著寫招標需求,趕緊發給項目組同事完事。

新問題


那邊在項目集成裏驗證也可以,正覺得沒事了,結果沒一會兒報過來,原來不管亂碼與否是可以選擇高亮的,現在雖然不亂碼了,但是選擇高亮的功能不好使了,所有的文字均無法選擇……

技術分享

如上圖所示,這個還是必須要的功能,真頭大,於是重新打開tomcat和編輯器檢查。

果然在本地純HTML環境下也是不能用,但是這個功能已經在FlowPaper的js裏了,又是大幾萬行js,看見幾行js就頭暈,這動輒就上萬代碼連個註釋都沒有……算了,冷靜想想,可能是PDF.js 1.5.x的版本有什麽函數變了?那幹脆換回1.5的版本,在那個上面調試一下,估計也是字體資源路徑的問題。

這裏又遇到一個坑,FlowPaper帶的js是壓縮過的,用還原工具格式化還原後,發現不僅僅是壓縮,連變量名都給混淆了,大量的函數a,函數b,變量a、b、c……好吧FlowPaper是商業軟件,但你用了開源PDF.js的東西雖然不用開源,這部分代碼沒必要混淆了吧。

為了改的方便,既然知道了明確的版本號,直接去PDF.js官網的git上從歷史版本裏找到這個版本拿下來,然後覆蓋上去,這樣總沒問題了吧?

結果又意外了,同樣版本覆蓋上去竟然不好使……這是什麽情況?拿文本比對工具比對了一下,發現差異還真大,主要是結構都不一致了,也看不出來哪裏不同了,只能把官方的源碼作為閱讀參照,直接在混淆代碼上修改。

但是混淆代碼也有問題,1.5和1.8的差異也不小,在1.8裏pdf.js裏的函數和賦值地方,在1.5的pdf.js裏根本沒有,但在pdf.worker.js裏有一段邏輯是這個意思,但嘗試修改之後,引發了新的問題,另外一段函數取值超限了,而那段自定義的超限函數,根本看不懂……

按照這個思路,越改需要修改的地方越多,而且本身這個也是個錯誤的思路,雖然想最偷懶的方式硬編碼去解決,但是破壞代碼原有的函數邏輯肯定是不對的。

又調了半天,文檔還沒進展,已經準備在QQ裏給同事留言先不管了,現在用的是免費版,讓他們去用收費版找廠商吧。

解決


正準備放棄,忽然想到搞了半天,cmaps下的一大堆bcmap文件到底是啥,雖然靠猜就知道和字體、編碼相關,但以前確實沒見過,google一下也算知其所以。結果就是這一查,徹底解決了問題。

stackoverflow上有人對這個文件也有疑問,提問了一下,雖然只有一個人回答,但回復的很詳盡,也完全解決了這個問題 https://stackoverflow.com/questions/32764773/what-is-a-pdf-bcmap-file

看到裏面說有默認全局設置和路徑,眼前一亮,現在遇到的問題不正是資源路徑的問題麽,js打印出來的路徑不對,那如果配置上默認路徑,是不是就可以了?

1.8裏有PDFJS這個全局變量,1.5版本裏也有,但是沒有這個屬性,於是在代碼中找到讀取配置賦值的地方(這下這裏寫定值沒問題了,本來就是固定配置),保存,刷新,測試,搞定!

原來PDF.js提供的demo裏是設置了默認路徑的,但是單純只提取js文件到FlowPaper下是沒有這個設置的,而且FlowPaper也沒有帶字體資源文件(免費版肯定沒有),所以雖然一開始發現字體資源文件我就把文件夾放到了FlowPaper下,但是以為js裏是通過相對路徑來獲取的。

簡單的總結:

1.FlowPaper免費版沒有帶字體資源文件,以及pdf.js的版本較低,某些中文編碼的pdf文件會出現亂碼

2.開源的程序可能文檔比較繁瑣,或者都是英文的,但如果不去大體了解下機制,單純從代碼層面去亂試必然事倍功半

3.在沒處理這個問題之前,同事想當然的認為是FlowPaper的bug,還發郵件去給開發團隊詢問(由於是免費版本對方當然不搭理),很多時候開發人員出問題都會先想到是bug,但更多要從自己是否使用正確入手來排查才行(雖然開源的系統bug會不少,但是穩定到一定版本之後隨便就能碰到bug的幾率還是少的,甚至還遇到一些同事開發中遇到問題直接指向說這個.Net Framworks有bug,這個JDK有bug,這也是屬於迷之自信了,不如按下心來排查自己的問題,往往都能解決)

FlowPaper中文PDF亂碼的一種解決辦法