使用freemarker模板生成Word文档和HTML

注:该文档是参考某个大佬的资料,根据自己的需要修改的,具体是哪位大佬的忘了,如果作者自己看到需要加明出处的,请留言你的博客地址

业务处理:

1,在业务中创建List<Map<String, Object>> data = new ArrayList<Map<String,Object>>(); 用来封装需要生成文档的数据

2,把数据都封装到集合后,再创建一个map,把封装好数据的list,放进该map中

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

maps.put("name", XXX);//封装数据

data.add(maps);//把封装的map添加到集合

Map<String, Object> mapsData = new HashMap<String, Object>();
mapsData.put("maps", data);//把集合加入到最终map中

3,调用工具,生成文档

参数为:封装好数据的map,是Word还是HTML,文档的名称,和模板

WordUtil.exportMillCertificateWord(request,response,mapsData,"word",word_name,"banbenshixiang.ftl");

工具类:

public class WordUtil {
//配置信息,代码本身写的还是很可读的,就不过多注解了
private static Configuration configuration = null;
//这里注意的是利用WordUtils的类加载器动态获得模板文件的位置
//private static final String templateFolder = WordUtil.class.getClassLoader().getResource("../../").getPath() + "WEB-INF/templetes/";
private static String templateFolder ="";
//private static final String templateFolder = "H:/我的项目/lm/lm/web/src/main/webapp/WEB-INF/templates";
/*static {
configuration = new Configuration();
configuration.setDefaultEncoding("utf-8");
try {
if (templateFolder.startsWith("/")) {
templateFolder = templateFolder.substring(1, templateFolder.length()-1);
}
configuration.setDirectoryForTemplateLoading(new File(templateFolder));
} catch (IOException e) {
e.printStackTrace();
}
}*/

private WordUtil() {
throw new AssertionError();
}

public static void exportMillCertificateWord(HttpServletRequest request, HttpServletResponse response, Map<String, Object> maps,
String type,String title,String ftlFile) throws IOException {
if (configuration == null) {
configuration = new Configuration();
configuration.setDefaultEncoding("utf-8");
}
try {
/*if (templateFolder.startsWith("/")) {
templateFolder = templateFolder.substring(1, templateFolder.length()-1);
}*/
templateFolder = request.getSession().getServletContext().getRealPath("/resources/template/word").toString();
configuration.setDirectoryForTemplateLoading(new File(templateFolder));
} catch (IOException e) {
e.printStackTrace();
}
Template freemarkerTemplate = configuration.getTemplate(ftlFile);
File file = null;
InputStream fin = null;
ServletOutputStream out = null;
try {
// 调用工具类的createDoc方法生成Word文档
file = createDoc(maps,freemarkerTemplate);
file.canWrite();
fin = new FileInputStream(file);

response.setCharacterEncoding("utf-8");
response.setContentType("application/msword");
// 设置浏览器以下载的方式处理该文件名
//String fileName = title+formatDateDetailTime(new Date()) + ".doc";
String fileName = "";
if (type.equals("word")) {
fileName = title + ".doc";
}else{
fileName = title + ".html";
}
response.setHeader("Content-Disposition", "attachment;filename="+new String(fileName.getBytes("gb2312"), "ISO8859-1"));

out = response.getOutputStream();
byte[] buffer = new byte[512]; // 缓冲区
int bytesToRead = -1;
// 通过循环将读入的Word文件的内容输出到浏览器中
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(); // 删除临时文件
}
}

private static File createDoc(Map<String, Object> maps, Template template) {
String name = "bumenxingzhengshenpiqingkuang.doc";
File f = new File(name);
Template t = template;
try {
// 这个地方不能使用FileWriter因为需要指定编码类型否则生成的Word文档会因为有无法识别的编码而无法打开
//System.out.println(maps);
Writer w = new OutputStreamWriter(new FileOutputStream(f), "utf-8");
t.process(maps, w);
w.close();
} catch (Exception ex) {
ex.printStackTrace();
throw new RuntimeException(ex);
}
return f;
}
public static String formatDateDetailTime(Date date){
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return sdf.format(date);
}
}

调用工具后,以流的方式写入到浏览器

生成Word时,文本内容无法自动换行,用\n和\r\n都没用,系统里的换行也没用,解决办法就是在需要换行的地方,添加字符串<w:br/>,才能在生成好的Word里看到换行

模板处理:

1,模板中固定好格式后,在需要动态填充数据的地方使用${数据字段}进行占位,有图片的话自动转换成base64字符串.

2,模板固定好后,另存为一个xml格式的文件,打开该xml文件,因为生成的xml文件模板,里面的一些元素生产的可能会把${XXX}给打乱,所以要手动修改下,把${  xml元素    xxx    xml元素}中的xml元素给删了,否则导致报错.

3,在动态的数据外,使用<#list maps as map>  </#list>给包裹起来,取值使用${map.xxx}

4,修改完成后,后缀名改为ftl,放到项目的指定目录下

需要注意的是,生成的模板中都是xml元素和你的动态数据变量,可能会混在一起,需要你自己仔细的观察修改,我自己生成Word时用的WPS的doc文档

猜你喜欢

转载自www.cnblogs.com/blogjava-blogs/p/9934352.html