Java根据FreeMarker模板生成Word(doc)文档(带图片)
前言:
客户需求给定一批word 然后利用代码生成固定格式的word,本例步骤则是 制作模板--读取word--写入模板--生成word
第一步:根据doc文档生成ftl模板
1:打开文档把需要替换的内容采用" **** "标识 如下图
2:将文档另存为xml格式 然后我们把****替换成freemarker标识,例如我的上述模板替换 ****改为${title} *****${name} ******${content}
此外,在插入图片的地方,会看到一段base64编码后的代码,我们将其替换为${image}
如果需要循环,则使用:<#list contentLst as content></#list> contentLst 是Map<String, Object>中key,值为数组,map为自定义;
如我本例中的正文需要根据段落来插入 则进行了遍历
如图
3:将xml文档 改成ftl后缀 则模板就制作完成了
第二步:读取文档,将数据塞入模板重新生成doc
1:读取ftl模板的代码示例
/** * @Author: chenpt * @Description: * @Date: Created in 2021-04-16 18:12 * @Modified By: */ public class WordUtils { //配置信息,代码本身写的还是很可读的,就不过多注解了 private static Configuration configuration = null; //这里注意的是利用WordUtils的类加载器动态获得模板文件的位置 // private static final String templateFolder = WordUtils.class.getClassLoader().getResource("../../").getPath() + "WEB-INF/templetes/"; private static final String templateFolder = "D:/test"; static { configuration = new Configuration(); configuration.setDefaultEncoding("utf-8"); try { configuration.setDirectoryForTemplateLoading(new File(templateFolder)); } catch (IOException e) { e.printStackTrace(); } } private WordUtils() { throw new AssertionError(); } /** * * @param request * @param response * @param map * @param title * @param ftlFile * @throws IOException */ public static void exportMillCertificateWord(HttpServletRequest request, HttpServletResponse response, Map map,String title,String ftlFile) throws IOException { Template freemarkerTemplate = configuration.getTemplate(ftlFile); File file = null; InputStream fin = null; ServletOutputStream out = null; try { // 调用工具类的createDoc方法生成Word文档 file = createDoc(map,freemarkerTemplate); fin = new FileInputStream(file); response.setCharacterEncoding("utf-8"); response.setContentType("application/msword"); // 设置浏览器以下载的方式处理该文件名 String fileName = title+ DateUtils.formatDateTime(new Date()) + ".doc"; response.setHeader("Content-Disposition", "attachment;filename=" .concat(String.valueOf(URLEncoder.encode(fileName, "UTF-8")))); 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<?, ?> dataMap, Template template) { String name = "test.doc"; File f = new File(templateFolder+File.separator+name); Template t = template; 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; } //获得图片的base64码 public static String getImageBase(String src) { // if(src==null||src==""){ // return ""; // } File file = new File("D:/test/test.png"); if(!file.exists()) { return ""; } InputStream in = null; byte[] data = null; try { in = new FileInputStream(file); } catch (FileNotFoundException e1) { e1.printStackTrace(); } try { data = new byte[in.available()]; in.read(data); in.close(); } catch (IOException e) { e.printStackTrace(); } BASE64Encoder encoder = new BASE64Encoder(); return encoder.encode(data); } public static void main(String[] args) throws IOException { List<String> contentLst = DocUtils.doc2Lst(new File("D:/test/杨浦 .doc")); //获得数据 Map<String, Object> map = new HashMap<String, Object>(); map.put("title", contentLst.get(0)); map.put("name", "陈澎涛"); for(int i=contentLst.size()-1;i>=0;i--){ if(i==0 || i==1){ contentLst.remove(i); } } map.put("contentLst",contentLst); map.put("file_num", "2021001"); map.put("username", "陈陈陈"); map.put("date1", "2021-04-17"); map.put("department", "上海市"); map.put("date2", "2021-04-17"); map.put("image", getImageBase("")); try { Template freemarkerTemplate = configuration.getTemplate("baitou.ftl"); WordUtils.createDoc(map,freemarkerTemplate); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
2:读取doc文档信息
/** * @Author: chenpt * @Description: * @Date: Created in 2021-04-17 15:37 * @Modified By: */ public class DocUtils { /** * 读取doc文件内容 * @param fs 想要读取的文件对象 * @return 返回文件内容 * @throws IOException */ public static String doc2String(FileInputStream fs) { WordExtractor re = null; try { StringBuilder result = new StringBuilder(); //获取word的所有文本 re = new WordExtractor(fs); result.append(re.getText()); return result.toString(); }catch (Exception e){ e.getCause(); }finally { try { re.close(); } catch (IOException e) { e.printStackTrace(); } } return ""; } /** * 根据段落读取doc内容 封装成list<段落> * @param file 想要读取的文件对象 * @return 返回文件内容 * @throws IOException */ public static List<String> doc2Lst(File file) { List<String> contentLst = new ArrayList<>(); WordExtractor re = null; try { FileInputStream fs = new FileInputStream(file); re = new WordExtractor(fs); String[] paraTexts = re.getParagraphText(); for(String s : paraTexts){ /***去除空格、跳过空行***/ if(!"".equals(s.trim())){ contentLst.add(s.trim()); } } return contentLst; }catch (Exception e){ e.getCause(); }finally { try { re.close(); } catch (IOException e) { e.printStackTrace(); } } return null; } public static String doc2String(File file) { String res = ""; try { res = doc2String(new FileInputStream(file)); }catch (Exception e){ e.printStackTrace(); } return res; } public static void main(String[] args) { File file = new File("D:/test/杨浦 .doc"); try { List<String> strings = doc2Lst(file); for (String s : strings){ System.out.println(s); } } catch (Exception e) { e.printStackTrace(); } } }
测试结果图:
作者:
不二尘
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。