一、 問題的提出
最近用java開發一個科技項目信息管理系統,里面有一個根據項目申請書的模板填寫項目申報信息的功能,有一個科技項目申請書word導出功能。
已有的實現方式:采用標准的jsp模板輸出實現,簡單地說,就是把數據渲染進jsp頁面,然后將此頁面另存為doc文檔,從而達到word導出效果。但是存在以下幾個問題:
(1) 由於導出的html網頁格式,打開word后,默認顯示的視圖模式為WEB版式視圖;
(2) 修改word文檔后,會新增一個相關聯的文件夾,word的html中會引用這個文件夾中的資源,比如樣式、圖片、主題等;這樣如果只轉移word文檔本身,會造成找不到相關聯的資源。
(3) 由於我們有些字段內容是采用富文本編輯器(百度的UEditor)填寫的,里面有附件的上傳(主要是圖片)。針對圖片,HTML的img標簽有一個src的屬性,這個src是服務器的圖片資源路徑。這個如果要顯示這個圖片的話,客戶的機器必須要保證聯網,這樣造成word不能離線存檔。
(4) 這樣導出的word打印出來的效果也是一塌糊塗,沒法接受。
正因為有這些問題,急需尋找另外一種解決方案。
二、 可用方案
在網上查找資料,總結出兩種比較可行的方案。
(1) 制作word模板,導出成mht文件(單頁面網頁格式),然后往模板里渲染數據,最終生成word文檔。
(2) 制作word模板,導出成xml文件,然后往模板里渲染數據,最終生成word文檔。
這兩種都是采用模板的思想,模板的制作比較加單,比用poi去組織word格式簡單的很多很多。唯一的不同點在於導出文件的格式不同,一個是mht文件,一個是xml文件。考慮到本項目中的項目申報書個別字段采用了富文本編輯器實現,保存進數據庫中是html格式的字符串,所以我們采用第一種方案,即通過mht文件來實現。
三、 思路整理與分析
1. mht文件的文件存儲結構分析
打開客戶提供的項目申報書模板文件,如,選擇“另存為-》其他格式”菜單,選擇“保存為mht文件(單網頁文件)”,如下圖所示:
保存后,用文本編輯器(UltraEdit或Sublime等)打開。打開后,有一些規律可循,具體關鍵的要點如下:
(1) mht文件的內容采用3Dus-ascii編碼格式,里面的中文字符串都被編碼成不可讀的內容;
(2) mht是單網頁文件,里面內嵌了很多資源內容,特別要注意的是圖片資源。我們查找“image”,會找到“image001””image002”。。。。等相關的匹配值。針對每個圖片(比如image002)有三個地方出現。
第一,在Html的<v:shape>標簽中,如下
第二,在內嵌資源塊中,對圖片的內容采用base64編碼。具體格式如下
第三,在文件的末尾部,有個<xml>標簽,里面有個HRef屬性標識,具體內容如下:
2. 具體的實現思路
(1) 制作word模板,用特定的模板引擎(我們用的freeMarker)的語法去生成占位符,然后導出出mht文件;
(2) 組織、處理數據,然后利用模板引擎去渲染模板。
(3) 將渲染后的結果保存為doc文件。
最重要的是第2個步驟中的處理數據。根據mht文件的格式要求,主要需要處理以下幾個地方。
(1) 將字符串類型的數據編碼成3Dus-ascii格式;
(2) 對富文本數據進行處理。主要是上述三個地方的處理,其一,對富文本的html中的img進行處理,轉換成<v:shape>標簽格式;其二,取出img的實際存儲位置,將圖片的內容按照base64進行編碼,並將編碼后內容添加進對應的位置;其三,在mht文件的末尾的xml標簽中加入相關資源引入字符串。
四、 實現步驟及注意事項
1. 根據模板引擎的語法規則填入占位符制作word模板,保存為mht文件。
另存為mht文件后,需用文本編輯器打開,主要綁定語句不能斷,比如${projectSbInfo.xmnamecn}另存為mht文件后,可能成了${projectSbInfo.=
xmnamecn}這個格式,需手動再修改一下。
另外還需在mht文件中插入圖片資源的base64及xml 的href引用的占位。如下圖
2. 組織、處理數據
一般的屬性數據組織起來簡單,無非就是從數據庫中獲取,處理也簡單。這里要特別注意以下數據的處理。
(1) html中image元素的處理。處理流程如下:
(2) 由於mht文件是采用的是“us-ascii”編碼,屬性后面都必須帶有3D前綴。所以包含html內容的需進行一下替換操作。
3.渲染模板,然后另存了word格式即可。
相關源代碼:http://files.cnblogs.com/files/liaofeifight/word.rar