framemarker导出word(含图片)
实现步骤:
1.编辑word模板,并将需要显示数据的地方标注出来。
2.将word模板另存为xml文件(为了兼容,最好使用Word 2003 XML文档)
3.替换标记。
使用xml编辑工具(我用的NotePad++)打开该xml文件,将标记的部分改为${tagName},如上文的number改为${number}。
注意:1.xml文件样式可能比较乱,为方便查看,可以使用xml在线格式化工具格式化。
2.图片占位的地方,会看到一片base64编码后的代码,把base64替换成${image}。
4.更改文件后缀为.ftl,注意:不要使用word代开ftl文件
5.代码实现:
index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>framemarker导出word</title> </head> <body> <form action="wordExport" method="post" name="form1"> <center> <h1>framemarker导出word</h1> <input type="submit" value="导出word"> </center> </form> </body> </html>
我自己的端口号为9080
编辑导出Word 的Servlet:
package com.framemarker.word.test; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.HashMap; import java.util.Map; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import sun.misc.BASE64Encoder; @SuppressWarnings("serial") public class WordExport extends HttpServlet { @Override protected void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { Map<String, Object> dataMap = new HashMap<String, Object>(); //存放成绩 Map<String, Object> reportMap = new HashMap<String, Object>(); reportMap.put("yuwen", "100"); reportMap.put("shuxue", "99"); reportMap.put("yingyu", "86"); reportMap.put("wuli", "75"); reportMap.put("huaxue", "80"); reportMap.put("shengwu", "90"); //存放个人信息及reportMap dataMap.put("number", "111222331"); dataMap.put("roomNo", "110"); dataMap.put("name", "张三"); dataMap.put("score", "100"); dataMap.put("image", WordUtils.imgEncode("C:/Users/HOME/Desktop/image.jpg")); dataMap.put("reportMap", reportMap); // 生成word并下载 File file = null; InputStream inputStream = null; ServletOutputStream out = null; String fileName = "test.doc"; String ftlName = "test1.ftl"; try { file = WordUtils.wordCreate(dataMap, fileName, ftlName); inputStream = new FileInputStream(file); res.setCharacterEncoding("UTF-8"); res.setContentType("application/msword"); res.addHeader("Content-Disposition", "attachment;filename = export.doc"); out = res.getOutputStream(); byte[] buffer = new byte[1024]; // 缓冲区 int bytesToRead = -1; // 通过循环将读入的Word文件的内容输出到浏览器中 while ((bytesToRead = inputStream.read(buffer)) != -1) { out.write(buffer, 0, bytesToRead); } } catch (Exception e) { // TODO: handle exception } finally { if (inputStream != null) inputStream.close(); if (out != null) out.close(); if (file != null) file.delete(); } } }
工具类:
package com.framemarker.word.test; import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStreamWriter; import java.io.Writer; import java.util.Map; import freemarker.template.Configuration; import freemarker.template.Template; import sun.misc.BASE64Encoder; public class WordUtils { /** * @param dataMap 存放标记和对应的值 * @param fileName 生成的临时word文件名 * @param ftlName 模板文件名 * @return 生成的临时word文件 * @throws IOException */ public static File wordCreate(Map<String, Object> dataMap, String fileName, String ftlName) throws IOException { Configuration configuration = new Configuration(); configuration.setDefaultEncoding("UTF-8"); // 使用包路径加载模板 configuration.setClassForTemplateLoading(WordUtils.class, "/com/framemarker/word/template"); File outFile = new File(fileName); Template template = null; try { template = configuration.getTemplate(ftlName); Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "UTF-8")); template.process(dataMap, writer); writer.flush(); writer.close(); } catch (Exception e) { // TODO: handle exception } return outFile; } /** * 根据绝对路径获取该图片的编码 * * @param absolutePath * @return * @throws IOException */ public static String imgEncode(String absolutePath) throws IOException { if (absolutePath == null || absolutePath == "") return ""; File file = new File(absolutePath); if (!file.exists()) return ""; InputStream in = null; byte[] data = null; try { in = new FileInputStream(file); data = new byte[in.available()]; in.read(data); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { in.close(); } BASE64Encoder encoder = new BASE64Encoder(); return encoder.encode(data); } }
6.结果实现
注意:有些标记不是简单替换就可以的,需要进行非空判断等操作,具体的需要去了解framemarker中标签的使用。