因为poi等输出word很麻烦,所以本文使用word编辑好模板,转成xml再转成ftl,在java中导入ftl模板,填充数据再生成为word下载或保存。
1、在Word中编辑好word模板,变量部分用el表达式替代
2、另存为xml文件(2003),打开xml文件,讲 sellerName等改为el表达式:${sellerName!}等,然后将.xml文件后缀改为.ftl,把.ftl模板文件到项目制定目录。加载jar包freemarker.jar然后开始后端代码
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.net.URLEncoder;
import java.util.Map;
import java.util.Properties;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.ClassUtils;
import freemarker.template.Configuration;
import freemarker.template.Template;
/**
* word模板工具类
* Title: WordGenerator
* Description:
* @author terry.peng
*/
public class WordGenerator {
private static Configuration configuration=null;
//private static final String templateFolder = WordGenerator.class.getClass().getResource("").getPath()+"/ftl/";
//private static final String templateFolder = WordGenerator.class.getClass().getResource("/" + ClassUtils.convertClassNameToResourcePath(WordGenerator.class.getPackage().getName())).getFile() + "/ftl";
private static final String templateFolder = "D:/ftl";
static{
configuration=new Configuration();
configuration.setDefaultEncoding("utf-8");
try {
configuration.setDirectoryForTemplateLoading(new File(templateFolder));
} catch (IOException e) {
e.printStackTrace();//throw new RuntimeException(e);
}
}
private WordGenerator() {
throw new AssertionError();
}
/**
* 下载合同
* @param map 要填充的数据模型
* @param docName 下载保存的名称(例如:销售合同.doc)
* @param ftlFile ftl模板名称(例如:sellerContract.ftl)
* @throws Exception
*/
public static void downContract(HttpServletRequest request, HttpServletResponse response, Map map,String docName,String ftlFile) throws Exception {
File file = null;
FileInputStream fin = null;
ServletOutputStream out = null;
try {
setDownloadHeader(request, response, docName);//设置下载头
// 调用工具类的createDoc方法生成Word文档
file = createDoc(request,response,map,docName,ftlFile);
fin = new FileInputStream(file.getAbsolutePath());
out = response.getOutputStream();
int len = 0;
byte[] buf = new byte[1024];
while ((len = fin.read(buf)) != -1) {
out.write(buf, 0, len);
}
out.flush();
} catch (Exception e) {
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
throw new Exception(e.getMessage(), e);
} finally {
if(fin != null) {
try {
fin.close();
} catch (Exception e) {
e.printStackTrace();
}
}
if(out != null) {
try {
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
if(file != null) {
try {
file.delete();// 删除临时文件
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
/**
* 导入ftl并创建doc
* @param request
* @param response
* @param dataMap
* @param docName
* @param ftlFile
* @return
* @throws IOException
*/
public static File createDoc(HttpServletRequest request, HttpServletResponse response,Map dataMap, String docName,String ftlFile) throws IOException {
Template template = configuration.getTemplate(ftlFile);
String name = templateFolder + File.separator + (int) (Math.random() * 100000) + docName;
File file = new File(name);
try { // 这个地方不能使用FileWriter因为需要指定编码类型否则生成的Word文档会因为有无法识别的编码而无法打开
Writer writer = new OutputStreamWriter(new FileOutputStream(file), "utf-8");
template.process(dataMap, writer);
// 关闭流
writer.flush();
writer.close();
} catch (Exception ex) {
ex.printStackTrace();
}
return file;
}
/** object转map
* Title: objectToMap
* Description:
* @param obj
* @return
*/
public static Map objectToMap(Object obj) {
if (obj == null) {
return null;
}
return new org.apache.commons.beanutils.BeanMap(obj);
}
/**
* map转Object
* Title: mapToObject
* Description:
* @param map
* @param beanClass
* @return
* @throws Exception
*/
public static Object mapToObject(Map map, Class beanClass)
throws Exception {
if (map == null)
return null;
Object obj = beanClass.newInstance();
org.apache.commons.beanutils.BeanUtils.populate(obj, map);
return obj;
}
/**
*
* @param request
* @param response
* @param fileName
*/
public static void setDownloadHeader(HttpServletRequest request, HttpServletResponse response, String fileName) {
String userAgent = request.getHeader("User-Agent");
boolean isIE = (userAgent != null) && (userAgent.toLowerCase().indexOf("msie") != -1);
response.setHeader("Pragma", "No-cache");
response.setHeader("Cache-Control", "must-revalidate, no-transform");
response.setDateHeader("Expires", 0L);
response.setContentType("application/x-download");
try {
if (isIE) {
fileName = new String(fileName.getBytes("gb2312"), "iso-8859-1");
response.setHeader("Content-Disposition", "attachment;filename=\"" + fileName + "\"");
} else {
fileName = new String(fileName.getBytes("gb2312"), "iso-8859-1");
response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
ftl模板中取值可以用el表达式取值${username}
如果要迭代list,String[]、或者在模板中做其他逻辑处理等,可以直接写freemarker的语言,例如:
0)> <#list goodsAttr as g>${g!}<#if g_has_next>]]> ]]>
<#list tradeRemark?split("\n") as g>${g!}<#if g_has_next>]]> ]]>
在xml中写freemarker语言要用原样输出
word转成的xml回车符号为
效果为
本文出处:https://blog.csdn.net/pdy8023/article/details/80339414