1.首先在Eclipse Java EE版中新建一個(gè)Dynamic Web Project娘扩,項(xiàng)目結(jié)構(gòu)如下圖所示
需要向項(xiàng)目中加入freemarker的JAR文件,可以通過(guò)下面的鏈接獲得Freemarker的最新版本:
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)入如下圖所示的界面: