freemarker优势:
很多时候我们构建的word文档都是有一定的格式标准,如果有多处地方都在生成同样格式的word文档,如果每一处都从头写,浪费时间,且大家的文档标准还不一定一样。完全可以事先创建好模板,然后直接往模板填值。
步骤:
1.本地创建word文档
2.将动态处的数据写成${data}格式,类似jquery
3.保存时选择文档格式为Word 2003 XML文档(*.xml)
4.用编辑软件修改这个xml文档,因为在编译成xml时,可能会出现问题,正常格式是xx${data1}xx${data2}xx,结果编译后是 xx${data1}xx${??da???ta2}xx,手动把????这些错误的字符删掉,然后以UTF-8编码保存为ftl文件
5.然后将ftl文件复制到项目,在freemarke构建项目时将会选择模板,填写值
6.将ftl文件粘贴到com.yinhai.demo.ftl下
7.查看代码
8.图片特殊处理,事先的word文档插入一个死图片,在更改xml时,把这个死图片对应的死base64码换个一个${img}占位符,在代码里面把对应图片的base64码赋值进这个占位符就好了
/** * 通过freemarker构建word文档 */ @RequestMapping("wordController!freemarkerToWord.do") public String freemarkerToWord() throws Exception{ HttpServletRequest req = getRequest(); HttpServletResponse resp = getResponse(); req.setCharacterEncoding("utf-8"); Map<String, Object> map = new HashMap<String, Object>(); Enumeration<String> paramNames = req.getParameterNames(); // 通过循环将表单参数放入键值对映射中 while(paramNames.hasMoreElements()) { String key = paramNames.nextElement(); String value = req.getParameter(key); map.put(key, value); } // 把图片对应的base64放进map,准备赋值给word模板 ServletContext servletContext = req.getServletContext(); InputStream is = servletContext.getResourceAsStream("/img/freemarker/ta3.jpg"); map.put("ta3_jpg", ImgToBase64Util.getImageString(is)); // 提示:在调用工具类生成Word文档之前应当检查所有字段是否完整 // 否则Freemarker的模板在处理时可能会因为找不到值而报错 这里暂时忽略这个步骤了 File file = null; InputStream fin = null; ServletOutputStream out = null; try { // 调用工具类WordGenerator的createDoc方法生成Word文档 file = WordGenerator.createDoc(map, "freemarker"); fin = new FileInputStream(file); resp.setCharacterEncoding("utf-8"); resp.setContentType("application/msword"); // 设置浏览器以下载的方式处理该文件默认名为freemarker.doc resp.addHeader("Content-Disposition", "attachment;filename=freemarker.doc"); out = resp.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();// 删除临时文件 } } return JSON; } ------------------------------------------------------------------------------------ 工具类: /** * 把Map里的值赋值进word模板,并返回File */ 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/yinhai/demo/ftl"); allTemplates = new HashMap<String, Template>(); try { //获取模板 allTemplates.put("freemarker", configuration.getTemplate("freemarker.ftl")); } catch (IOException e) { e.printStackTrace(); throw new RuntimeException(e); } } private WordGenerator() { throw new AssertionError(); } 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 { // 这个地方不能使用FileWriter因为需要指定编码类型否则生成的Word文档会因为有无法识别的编码而无法打开 Writer w = new OutputStreamWriter(new FileOutputStream(f), "utf-8"); t.process(dataMap, w); w.close(); } catch (Exception ex) { ex.printStackTrace(); throw new RuntimeException(ex); } return f; } } ---------------------------------------------------------------------------------------------------------- /** * 图片的InputStream转成base64 */ public class ImgToBase64Util { public static String getImageString(InputStream is) throws IOException { byte[] data = null; try { data = new byte[is.available()]; is.read(data); is.close(); } catch (IOException e) { throw e; } finally { if(is != null) { is.close(); } } BASE64Encoder encoder = new BASE64Encoder(); return data != null ? encoder.encode(data) : ""; } }