FreeMark導(dǎo)出word文檔

1.首先在Eclipse Java EE版中新建一個(gè)Dynamic Web Project娘扩,項(xiàng)目結(jié)構(gòu)如下圖所示


需要向項(xiàng)目中加入freemarker的JAR文件,可以通過(guò)下面的鏈接獲得Freemarker的最新版本:

http://freemarker.org/freemarkerdownload.html

2.模板文件resume.ftl是如何生成的呢油猫,其實(shí)非常簡(jiǎn)單夕凝,將需要的Word文檔做好之后铃绒,選擇另存為XML文件鸽照,另存之后建議用Editplus、Notepad++颠悬、Sublime等工具打開(kāi)查看一下矮燎,因?yàn)橛械臅r(shí)候你寫(xiě)的占位符可能會(huì)被拆開(kāi),這樣Freemarker就無(wú)法處理了赔癌。


打開(kāi)XML文件看看吧诞外,如果剛才你寫(xiě)的${title}、${name}被xml文件給拆散了灾票,修改一下XML文件就OK了峡谊。


修改過(guò)后另存為resume.ftl模板文件,如下所示:

3.接下來(lái)就是Servlet(也可以是Struts2的Action刊苍、Spring MVC的Controller等)和工具類WordGenerator的編寫(xiě)以及頁(yè)面test.jsp的制作了既们,代碼如下所示:

protected?void?doPost(HttpServletRequest req, HttpServletResponse resp) throws?ServletException, IOException {

req.setCharacterEncoding("utf-8");

Map<String,Object> map?= new?HashMap<String,Object>();

Enumeration<String> paramNames?= req.getParameterNames();

//通過(guò)循環(huán)將表單中的參數(shù)放入鍵值對(duì)映射中

while(paramNames.hasMoreElements()){

String key?= paramNames.nextElement();

String value?= req.getParameter(key);

map.put(key, value);

}

/*提示:在調(diào)用工具類生成Word文檔之前應(yīng)當(dāng)檢查所有字段是否完整(因?yàn)樵趂reemark中沒(méi)有對(duì)null進(jìn)行出來(lái),如果值是null的話

freemark將會(huì)報(bào)錯(cuò))*/

//否則Freemarker的模板殷勤在處理時(shí)可能會(huì)因?yàn)檎也坏街刀鴪?bào)錯(cuò)這里暫時(shí)忽略這個(gè)步驟了

File file?= null;

InputStream fin?= null;

ServletOutputStream out?= null;

try{

file?= WordGenerator.createDoc(map,"resume");

fin?= new?FileInputStream(file);

resp.setCharacterEncoding("utf-8");

resp.setContentType("application/msword");

// 設(shè)置瀏覽器以下載的方式處理該文件默認(rèn)名為resume.doc

resp.addHeader("Content-Disposition", "attachment;filename=resume.doc");

out?= resp.getOutputStream();

byte[] buffer?= new?byte[1024];

int?bytesToRead?= -1;

// 通過(guò)循環(huán)將讀入的Word文件的內(nèi)容輸出到瀏覽器中

while((bytesToRead?= fin.read(buffer)) != -1) {

out.write(buffer, 0, bytesToRead);

}

}finally{

if(fin?!= null) fin.close();

if(out?!= null) out.close();

if(file?!= null) file.delete(); // 刪除臨時(shí)文件

}

}

import?java.io.File;

import?java.io.FileOutputStream;

import?java.io.IOException;

import?java.io.OutputStreamWriter;

import?java.io.Writer;

import?java.util.HashMap;

import?java.util.Map;

import?freemarker.template.Configuration;

import?freemarker.template.Template;


public?class?WordGenerator {

private?static?Configuration configuration?= null;

private?static?Map<String,Template> allTemplates?= null;

static{

configuration?= new?Configuration();

configuration.setDefaultEncoding("utf-8");

configuration.setClassForTemplateLoading(WordGenerator.class,"/com/yuan/ftl");

allTemplates?= new?HashMap<String, Template>();

try?{

allTemplates.put("resume",configuration.getTemplate("resume.ftl"));

} catch?(IOException e) {

e.printStackTrace();

}

}

public?static?File createDoc(Map<?,?>dataMap,String type){

String name?= "temp"+(int)(Math.random()*100000)+".doc";

File f?= new?File(name);

Template t?= allTemplates.get(type);

try{

Writer w?= new?OutputStreamWriter(new?FileOutputStream(f),"utf-8");

t.process(dataMap, w);

w.close();

}catch(Exception e){

e.printStackTrace();

}

return?f;

}

}

JSP頁(yè)面的代碼:

<%@?page?pageEncoding="UTF-8"%>

<!DOCTYPE?html>

<html>

<head>

<meta?charset="UTF-8"?/>

<title>Document</title>

<style?type="text/css">

*?{ font-family: "微軟雅黑"; }

.textField?{ border:none; border-bottom: 1px solid gray; text-align: center; }

#file?{ border:1px solid black; width: 80%; margin:0 auto; }

h1?input{ font-size:72px; }

td?textarea?{ font-size: 14px; }

.key?{ width:125px; font-size:20px; }

</style>

</head>

<body>

<form?action="MyServlet"?method="post">

<div?id="file"?align="center">

<h1><input?type="text"?name="title"?class="textField"?value="我的簡(jiǎn)歷"/></h1>

<hr/>

<table>

<tr>

<td?class="key">姓名:</td>

<td><input?type="text"?name="name"?class="textField"/></td>

<td?class="key">性別:</td>

<td>

<input?type="radio"?name="gender"?value="男"?checked/>男

<input?type="radio"?name="gender"?value="女"?/>女

</td>

</tr>

<tr>

<td?class="key">聯(lián)系電話:</td>

<td><input?type="text"?name="tel"?class="textField"/></td>

<td?class="key">家庭住址:</td>

<td><input?type="text"?name="address"?class="textField"/></td>

</tr>

<tr>

<td?colspan="4"?class="key">個(gè)人簡(jiǎn)介:</td>

</tr>

<tr>

<td?colspan="4">

<textarea?rows="10"?cols="100"?name="content"></textarea>

</td>

</tr>

</table>

</div>

<div?align="center"?style="margin-top:15px;">

<input?type="submit"?value="保存Word文檔"?/>

</div>

</form>

</body>

</html>

5.此外正什,如果你希望在Word文檔中插入圖片啥纸,可以把Word另存為的XML文件中代表圖片的那個(gè)很長(zhǎng)的字符串(BASE64編碼的字符串)換成一個(gè)占位符,在將要插入Word文檔的圖片對(duì)象轉(zhuǎn)換成BASE64編碼的字符串婴氮,用該字符串替換掉占位符就可以了斯棒,示意圖和代碼如下所示:

6.將圖片轉(zhuǎn)換成BASE64字符串的代碼如下所示:

public static String getImageString(String filename) throws IOException {

?InputStream in = null;

?????????byte[] data = null;

?????????try {

?????????????in = new FileInputStream(filename);

?????????????data = new byte[in.available()];

?????????????in.read(data);

?????????????in.close();

?????????} catch (IOException e) {

?????????????throw e;

?????????} finally {

???????? ?if(in != null) in.close();

?????????}

?????????BASE64Encoder encoder = new BASE64Encoder();

?????????return data != null ? encoder.encode(data) : "";

}

7.注意:這里使用的BASE64Encoder類在sun.misc包下,rt.jar中有這個(gè)類主经,但是卻無(wú)法直接使用荣暮,需要修改訪問(wèn)權(quán)限,在Eclipse中可以這樣修改

在項(xiàng)目上點(diǎn)右鍵選擇Properties菜單項(xiàng)進(jìn)入如下圖所示的界面:


?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末旨怠,一起剝皮案震驚了整個(gè)濱河市渠驼,隨后出現(xiàn)的幾起案子蜈块,更是在濱河造成了極大的恐慌鉴腻,老刑警劉巖迷扇,帶你破解...
    沈念sama閱讀 217,542評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異爽哎,居然都是意外死亡蜓席,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門课锌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)厨内,“玉大人,你說(shuō)我怎么就攤上這事渺贤〕福” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,912評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵志鞍,是天一觀的道長(zhǎng)瞭亮。 經(jīng)常有香客問(wèn)我,道長(zhǎng)固棚,這世上最難降的妖魔是什么统翩? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,449評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮此洲,結(jié)果婚禮上厂汗,老公的妹妹穿的比我還像新娘。我一直安慰自己呜师,他們只是感情好娶桦,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著匣掸,像睡著了一般趟紊。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上碰酝,一...
    開(kāi)封第一講書(shū)人閱讀 51,370評(píng)論 1 302
  • 那天霎匈,我揣著相機(jī)與錄音,去河邊找鬼送爸。 笑死铛嘱,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的袭厂。 我是一名探鬼主播墨吓,決...
    沈念sama閱讀 40,193評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼纹磺!你這毒婦竟也來(lái)了帖烘?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,074評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤橄杨,失蹤者是張志新(化名)和其女友劉穎秘症,沒(méi)想到半個(gè)月后照卦,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,505評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡乡摹,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評(píng)論 3 335
  • 正文 我和宋清朗相戀三年役耕,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片聪廉。...
    茶點(diǎn)故事閱讀 39,841評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡瞬痘,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出板熊,到底是詐尸還是另有隱情框全,我是刑警寧澤,帶...
    沈念sama閱讀 35,569評(píng)論 5 345
  • 正文 年R本政府宣布干签,位于F島的核電站竣况,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏筒严。R本人自食惡果不足惜丹泉,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望鸭蛙。 院中可真熱鬧摹恨,春花似錦、人聲如沸娶视。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,783評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)肪获。三九已至寝凌,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間孝赫,已是汗流浹背较木。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,918評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留青柄,地道東北人伐债。 一個(gè)月前我還...
    沈念sama閱讀 47,962評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像致开,于是被迫代替她去往敵國(guó)和親峰锁。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評(píng)論 2 354

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