轉載請注明出處 https://www.cnblogs.com/majianming/p/9537173.html
項目中需要對訂單生成pdf文件,在不斷的嘗試之后,終於生成了比較滿意的pdf文檔。
簡單介紹一下背景:項目是一個erp項目,docker容器化CentOS 7運行環境,應用打包方式jar,使用itext生成pdf
我們從后面的三個背景來分析
- 首先是使用itext庫,需要明確的是itext是默認不支持中文顯示的,這個問題很容易找到的方法是添加itext-asin庫,一個解決中日韓文字問題的拓展,而在這個拓展自然也是需要另外添加中文字體支持的,所以我們為了支持中文,在itext的基礎上需要itext-asin庫和字體文件。
- 第二個背景,也就是jar打包方式,許多博客在介紹這一段時,會把字體文件添加到項目文件下,這樣本地開發是沒有問題的,但是一旦部署到了linux(CentOS)環境下,就會有中文字無法顯示的問題(這時候如果你將應用的jar包在windows環境下跑,一般是可以正常顯示的,為什么?等會看看第三個背景你就會明白了),這是因為在itext中,並不是用文件流(fileinputstream)的形式去讀取字體,自然無法讀取到jar包中的文件,那么我們換一個思路,把字體文件移動到項目外的一個路徑下,然后指定itext去讀取這個路徑。
- 第三個背景CentOS,一般的服務器環境自然不會帶中文字體的,那么我們需要將添加字體到哪里?隨便加一個地方?且慢,我們先看一個地方
在com.itextpdf.text.FontFactoryImp#registerDirectories()
下,我們發現了這樣一段代碼
String windir = System.getenv("windir");
String fileseparator = System.getProperty("file.separator");
if (windir != null && fileSeparator != null) {
fontResolver.addFontDirectory(windir + fileseparator + "fonts", BaseFont.NOT_EMBEDDED);
}
fontResolver.addFontDirectory("/usr/share/X11/fonts", BaseFont.EMBEDDED);
fontResolver.addFontDirectory("/usr/X/lib/X11/fonts", BaseFont.EMBEDDED);
fontResolver.addFontDirectory("/usr/openwin/lib/X11/fonts", BaseFont.EMBEDDED);
fontResolver.addFontDirectory("/usr/share/fonts", BaseFont.EMBEDDED);
fontResolver.addFontDirectory("/usr/X11R6/lib/X11/fonts", BaseFont.EMBEDDED);
fontResolver.addFontDirectory("/Library/Fonts", BaseFont.EMBEDDED);
fontResolver.addFontDirectory("/System/Library/Fonts", BaseFont.EMBEDDED);
也就是說,itext已經把背景分析2中的指定字體路徑的事情做了,只是我們還沒有字體在對應的路徑上
然后我們再看看其中的這個代碼
String windir = System.getenv("windir");
String fileseparator = System.getProperty("file.separator");
if (windir != null && fileSeparator != null) {
fontResolver.addFontDirectory(windir + fileseparator + "fonts", BaseFont.NOT_EMBEDDED);
}
windir? 比較熟悉windows下變量的人可以知道,這個是獲取windows系統根路徑的一個環境變量,我是win 10的電腦,獲取的就是C:\Windows。
我們打開C:\Windows\fonts路徑,會發現都是相關字體文件,也就是解釋了為什么在linux中文無法顯示的jar包在Windows下可以正常顯示了——並不是在windows下可以讀取到jar包的字體文件,而是在windows下可以讀取到系統中的字體文件。
因為這個原因,自然可以顯示中文字體;所以,如果要顯示任何自定義的字體,在windows下,我們可以將可以添加到C:\Windows\fonts下;在liunx環境下,添加到對應的路徑下即可。我們理論上可以使用任何一個系統中已經定義的字體。在這里,我們選擇了/usr/share/fonts這個路徑,當然這個路徑在CentOS中是不存在的,所以要手動創建,然后將需要的中文字體復制進去
因為公司的環境是k8s的docker容器,為了平時的docker容器部署方便,我們依然把字體文件放在工程下(與dockerfile同一級),然后使用docker的命令將字體復制到指定路徑下
COPY ./fonts/ /usr/share/fonts/