linux服務(wù)器實(shí)現(xiàn)Word文檔轉(zhuǎn)PDF文檔

這兩天遇到一個財務(wù)系統(tǒng)的需求晃危,其中一個模塊中客戶提供了Word文檔模板

根據(jù)數(shù)據(jù)庫查詢的結(jié)果填充模板,響應(yīng)瀏覽器pdf下載流老客。

具體實(shí)現(xiàn)如下:

引用依賴:freemarker僚饭,aspose-words-15.8.0-jdk16.jar--->需要百度自行下載,maven中央倉庫沒有

<!-- word2pdf -->

? ? ? ? <dependency>

? ? ? ? ? ? <groupId>com.jcraft</groupId>

? ? ? ? ? ? <artifactId>aspose-words</artifactId>

? ? ? ? ? ? <version>15.8.0-jdk16</version>

? ? ? ? </dependency>

????<dependency>

????????<groupId>org.freemarker</groupId>

????????<artifactId>freemarker</artifactId>

????????<version>2.3.18</version>

????</dependency>

freemarker作為替換文檔中變量所需插件胧砰,首先將doc,docx文檔打開鳍鸵,直接另存為xml格式,注意千萬不要直接改文件后綴尉间!

保存完畢后再將文件的后綴名改為.tfl权纤,這樣一來freemarker就可以識別到文件中待替換的變量,請注意在修改完后綴名后一定要用文本編輯器打開檢查文件乌妒,word的格式問題可能導(dǎo)致變量符號被擠開陨簇,發(fā)現(xiàn)有被擠開的變量符號請手動修復(fù)赋除,建議用文本編輯器查找${快速檢查。

接下來在項(xiàng)目resouses目錄下/linux環(huán)境則在classes目錄下新建license.xml文件宜肉。

文件中的內(nèi)容如下

<License>

<Data>

<Products>

<Product>Aspose.Total for Java</Product>

<Product>Aspose.Words for Java</Product>

</Products>

<EditionType>Enterprise</EditionType>

<SubscriptionExpiry>20991231</SubscriptionExpiry>

<LicenseExpiry>20991231</LicenseExpiry>

<SerialNumber>23dcc79f-44ec-4a23-be3a-03c1632404e9</SerialNumber>

</Data>

<Signature>0nRuwNEddXwLfXB7pw66G71MS93gW8mNzJ7vuh3Sf4VAEOBfpxtHLCotymv1PoeukxYe31K441Ivq0Pkvx1yZZG4O1KCv3Omdbs7uqzUB4xXHlOub4VsTODzDJ5MWHqlRCB1HHcGjlyT2sVGiovLt0Grvqw5+QXBuinoBY0suX0=</Signature>

</License>

接下來將Windows下字體庫上傳到linux损话,Windows下字體庫的位置為C:\Windows\fonts

linux的字體庫是 /usr/share/fonts

將windows下的字體打包上傳到linux上:/usr/share/fonts/chinese? ,然后解壓即可

準(zhǔn)備工作完畢侦啸,接下來上代碼!

所需的工具類:

import com.aspose.words.Document;

import com.aspose.words.FontSettings;

import com.aspose.words.License;

import com.aspose.words.SaveFormat;

import java.io.File;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.InputStream;

public class WordToPdfUtil {

public? boolean getLicense() {

boolean result =false;

try {

System.out.println(this.getClass().getClassLoader().getResource("license.xml").toString());

//InputStream is =this.getClass().getClassLoader().getResourceAsStream("license.xml");

? ? ? ? ? ? InputStream is =this.getClass().getClassLoader().getResourceAsStream("license.xml");

License aposeLic =new License();

aposeLic.setLicense(is);

result =true;

}catch (Exception e) {

e.printStackTrace();

}

return result;

}

/*public static void main(String[] args) throws Exception {

WordToPdfUtil bean = new WordToPdfUtil();

bean.word2Pdf2("D:\\TEST.doc","D:\\TEST.pdf");

}*/

/**

? ? * inpath: 輸入word的路徑丧枪,例如: C:\\TEST.doc

? ? * outpath: 輸出pdf的路徑光涂,例如: C:\\TEST.pdf

*/

? ? public? void word2Pdf2(String inpath,String outpath)throws Exception {

if (!getLicense()) {// 驗(yàn)證License 若不驗(yàn)證則轉(zhuǎn)化出的pdf文檔會有水印產(chǎn)生

? ? ? ? ? ? System.out.println("非法------------");

return;

}

long old = System.currentTimeMillis();

File file =new File(outpath);

FileOutputStream os =new FileOutputStream(file);

//解決亂碼

? ? ? ? //如果是windows執(zhí)行,不需要加這個

? ? ? ? //TODO 如果是linux執(zhí)行拧烦,需要添加這個*****

? ? ? ? FontSettings.setFontsFolder("/usr/share/fonts/chinese",false);

Document doc =new Document(inpath);//Address是將要被轉(zhuǎn)化的word文檔

? ? ? ? doc.save(os, SaveFormat.PDF);//全面支持DOC, DOCX, OOXML, RTF HTML, OpenDocument, PDF, EPUB, XPS, SWF 相互轉(zhuǎn)換

? ? ? ? long now = System.currentTimeMillis();

System.out.println("共耗時:" + ((now - old) /1000.0) +"秒");

}

/**

? ? * @param path? ? ? pdf輸出路徑

? ? * @param wordInput word輸入流

? ? * @param wordName? word文檔的名稱

? ? */

? ? public? void word2pdf(String path, InputStream wordInput, String wordName)throws FileNotFoundException {

if (!getLicense()) {// 驗(yàn)證License 若不驗(yàn)證則轉(zhuǎn)化出的pdf文檔會有水印產(chǎn)生

? ? ? ? ? ? System.out.println("非法");

return;

}

long old = System.currentTimeMillis();

File file =new File(path + wordName +".pdf");//新建一個空白pdf文檔

? ? ? ? FileOutputStream os =new FileOutputStream(file);

Document doc =null;//Address是將要被轉(zhuǎn)化的word文檔

? ? ? ? try {

doc =new Document(wordInput);

}catch (Exception e) {

e.printStackTrace();

}

try {

doc.save(os, SaveFormat.PDF);//全面支持DOC, DOCX, OOXML, RTF HTML, OpenDocument, PDF, EPUB, XPS, SWF 相互轉(zhuǎn)換

? ? ? ? }catch (Exception e) {

e.printStackTrace();

}

long now = System.currentTimeMillis();

System.out.println("共耗時:" + ((now - old) /1000.0) +"秒");//轉(zhuǎn)化用時

? ? }

}

contorller層代碼忘闻,筆者所用的框架比較老,可以參考一下:

public String preview(HttpServletRequest request, HttpServletResponse response,SettlementForm settlementForm)throws IOException {

String type = settlementForm.getType();

? ? if(settlementForm.getType().equals("元")){

settlementForm.setType("0");

}

if(settlementForm.getType().equals("小")){

settlementForm.setType("1");

}if(settlementForm.getType().equals("P")){

settlementForm.setType("2");

}

//根據(jù)合作方名稱查詢合作方子業(yè)務(wù)名稱

? ? String businessName =partnerSettleFromDao.findBusinessNameByPartnerName(settlementForm.getUserName());

//boolean flag = partnerSettleFromDao.updatePartnerStatus(settlementForm);

? ? ? ? try {

//合作方確認(rèn)賬單成功恋博,下載word結(jié)算單

? ? ? ? ? ? //導(dǎo)出結(jié)算單模板

? ? ? ? ? ? String tmpFile =this.getClass().getClassLoader().getResource("/").getPath()+"template/";

Configuration configuration =new Configuration();

configuration.setDefaultEncoding("utf-8");

configuration.setDirectoryForTemplateLoading(new File(tmpFile));

Template template = configuration.getTemplate("template.ftl","utf-8");

//System.out.println(template.toString());

? ? ? ? ? ? //編輯替換模板的數(shù)據(jù)齐佳,需要和模板中變量名一一對應(yīng)

? ? ? ? ? ? Map map =new HashMap<>();

map.put("type",type);

map.put("businessName",businessName);

map.put("username",settlementForm.getUserName());

map.put("accountPeriod",settlementForm.getAccountPeriod());

map.put("month",settlementForm.getAccountPeriod());

map.put("settleToCPAccount",settlementForm.getSettleToCPAccount());

//獲取輸出流

? ? ? ? ? ? //ServletOutputStream os = response.getOutputStream();

? ? ? ? ? ? File outFile =new File(tmpFile+"/test.docx");

Writer ot =new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile),

"utf-8"),10240);

template.process(map, ot);

? ? ? ? ? ? File outputFile =new File("test.pdf");

WordToPdfUtil bean =new WordToPdfUtil();

? ? ? ? ? ? bean.word2Pdf2(tmpFile+"/test.docx",tmpFile+"/test.pdf");

? ? ? ? ? ? InputStream inputStream=new FileInputStream(tmpFile+"/test.pdf");//根據(jù)路徑獲取要下載的文件輸入流PDF

? ? ? ? ? ? ServletOutputStream os = response.getOutputStream();

byte[] b=new byte[1024];//緩沖區(qū)

? ? ? ? ? ? int length;

// 重置輸出流

? ? ? ? ? ? response.reset();

response.setHeader("Content-disposition",

"attachment; filename=" +new String(settlementForm.getAccountPeriod().getBytes(),"8859_1")

+new String(settlementForm.getUserName().getBytes(),"8859_1") +".pdf");

response.setContentType("application/msword");

//response.setCharacterEncoding("UTF-8");

? ? ? ? ? ? while((length=inputStream.read(b))>0){//把文件流寫到緩沖區(qū)里

? ? ? ? ? ? ? ? os.write(b,0,length);

}

//System.out.println(template.toString());

? ? ? ? ? ? os.flush();

os.close();

return "true";

}catch (Exception e){

log.error("下載結(jié)算單出錯"+e);

e.printStackTrace();

return "false";

}

}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末私恬,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子炼吴,更是在濱河造成了極大的恐慌本鸣,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,695評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件硅蹦,死亡現(xiàn)場離奇詭異荣德,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)童芹,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評論 3 399
  • 文/潘曉璐 我一進(jìn)店門涮瞻,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人辐脖,你說我怎么就攤上這事饲宛。” “怎么了嗜价?”我有些...
    開封第一講書人閱讀 168,130評論 0 360
  • 文/不壞的土叔 我叫張陵艇抠,是天一觀的道長。 經(jīng)常有香客問我久锥,道長家淤,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,648評論 1 297
  • 正文 為了忘掉前任瑟由,我火速辦了婚禮絮重,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘歹苦。我一直安慰自己青伤,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,655評論 6 397
  • 文/花漫 我一把揭開白布殴瘦。 她就那樣靜靜地躺著狠角,像睡著了一般。 火紅的嫁衣襯著肌膚如雪蚪腋。 梳的紋絲不亂的頭發(fā)上丰歌,一...
    開封第一講書人閱讀 52,268評論 1 309
  • 那天,我揣著相機(jī)與錄音屉凯,去河邊找鬼立帖。 笑死,一個胖子當(dāng)著我的面吹牛悠砚,可吹牛的內(nèi)容都是我干的晓勇。 我是一名探鬼主播,決...
    沈念sama閱讀 40,835評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼宵蕉!你這毒婦竟也來了酝静?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,740評論 0 276
  • 序言:老撾萬榮一對情侶失蹤羡玛,失蹤者是張志新(化名)和其女友劉穎别智,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體稼稿,經(jīng)...
    沈念sama閱讀 46,286評論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡薄榛,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,375評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了让歼。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片敞恋。...
    茶點(diǎn)故事閱讀 40,505評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖谋右,靈堂內(nèi)的尸體忽然破棺而出硬猫,到底是詐尸還是另有隱情,我是刑警寧澤改执,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布啸蜜,位于F島的核電站,受9級特大地震影響辈挂,放射性物質(zhì)發(fā)生泄漏衬横。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,873評論 3 333
  • 文/蒙蒙 一终蒂、第九天 我趴在偏房一處隱蔽的房頂上張望蜂林。 院中可真熱鬧,春花似錦拇泣、人聲如沸噪叙。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽构眯。三九已至,卻和暖如春早龟,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背猫缭。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評論 1 272
  • 我被黑心中介騙來泰國打工葱弟, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人猜丹。 一個月前我還...
    沈念sama閱讀 48,921評論 3 376
  • 正文 我出身青樓芝加,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子藏杖,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,515評論 2 359

推薦閱讀更多精彩內(nèi)容

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法将塑,類相關(guān)的語法,內(nèi)部類的語法蝌麸,繼承相關(guān)的語法点寥,異常的語法,線程的語...
    子非魚_t_閱讀 31,664評論 18 399
  • 大家好来吩,我是傻明蠶豆敢辩,最近搞了一個html轉(zhuǎn)pdf,在這里把知識記錄下來弟疆,希望對大家有幫助戚长。 廢話不多說,直奔主題...
    傻明蠶豆閱讀 1,331評論 0 2
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理怠苔,服務(wù)發(fā)現(xiàn)同廉,斷路器,智...
    卡卡羅2017閱讀 134,702評論 18 139
  • 說明:解決上傳文件亂碼問題柑司,上傳文件件迫肖,附帶參數(shù)等。 引入包: org.apache.httpcomponents...
    MrLe688閱讀 979評論 0 0
  • 1.首先在Eclipse Java EE版中新建一個Dynamic Web Project帜羊,項(xiàng)目結(jié)構(gòu)如下圖所示 需...
    G__yuan閱讀 1,381評論 0 0