如何使用freeMarker生成doc、docx、pdf文件

freeMarker是什么
doc和docx有什么区别
如何生成doc文档(带图片)
如何生成docx文档,以及将其生成pdf文档

  1. freeMarker是什么

    http://freemarker.foofun.cn/

  2. doc和docx有什么区别
    格式不同
    DOCX是WORD2007及以上版的格式,是一种基于XML的压缩格式。
    DOC是WORD2003及以下版的格式。
    体积不同,docx远大于doc
    doc是单个文件,而docx其实是由一个zip压缩文件更改后缀而来

  3. 如何生成doc文档
    由1可以明白freemarker可以输出文本信息, 而我们的doc其实就是一个文本,所以可以直接使用freemarker可以doc文件,将doc文件,另存为xml文件,修改成动态数据模板,如果带有图片,可直接由图片转成base64格式,再按照普通属性进行替换(此处我们重点说生成docx文档,因为生成pdf文档,poi对freemark生成的doc文档转成pdf无法辨识)

  4. 如何生成docx文档,以及将其生成pdf文档
    docx是一个zip压缩文件,解压后的内容如下:



    主要关注:document.xml (文档结构),document.xml.rels(图片引用关系配置),以及media(存放图片的目录)目录
    还是直接上代码吧
    首先写一个要生成的docx样式,修改后缀为zip,然后将其解压,设置动态数据,修改document.xml 和document.xml.rels文件按照freeMarker数据格式编写
    document.xml (文档结构,橘色部分freemarker需要设置的动态数据):

    文档结构,橘色部分freemarker引用document.xml.rels中的id:

    document.xml.rels(图片引用关系配置,橘色部分freemarker需要动态生成的图片引用id)

依赖jar

<dependency><groupId>org.freemarker</groupId><artifactId>freemarker</artifactId><version>2.3.23</version></dependency><dependency><groupId>com.artofsolving</groupId><artifactId>jodconverter-maven-plugin</artifactId><version>2.2.1</version></dependency  <dependency><groupId>fr.opensagres.xdocreport</groupId><artifactId>org.apache.poi.xwpf.converter.core</artifactId><version>1.0.5</version></dependency><dependency><groupId>fr.opensagres.xdocreport</groupId><artifactId>org.apache.poi.xwpf.converter.pdf</artifactId><version>1.0.5</version></dependency>

public class XMlToDocx {private static String OS = System.getProperty("os.name").toLowerCase();/*** 根据数据生成文本*@param dataMap 数据*@param outFilePath 生成的document.xml和document.xml.rels对应的目录名称*@param template 模板对象*@throws Exception*/private static  void toText(Map<String,Object> dataMap,String outFilePath,Template template)throws Exception  {File docFile = new File(outFilePath);FileOutputStream fos = new FileOutputStream(docFile);Writer out = new BufferedWriter(new OutputStreamWriter(fos),10240);template.process(dataMap,out);if(out != null){out.close();}}/*** 生成word docx*@param dataMap 数据*@param ftlPath  ftl存放的目录(模板)*@param docFilePath 生成的document.xml和document.xml.rels对应的目录名称*@param fileList fileList 图片文件*@throws Exception*/public static  void makeWord(Map<String,Object> dataMap,String ftlPath,String docFilePath,  List<File> fileList) throws Exception {/** 初始化配置文件 **/Configuration configuration = new Configuration();String fileDirectory = ftlPath;/** 加载文件 **/configuration.setDirectoryForTemplateLoading(new File(fileDirectory));/** 加载模板 **/Template template = configuration.getTemplate("document.xml");/** 指定输出word文件的路径 **/String outFilePath = docFilePath+".xml";toText(dataMap,outFilePath,template);template = configuration.getTemplate("document.xml.rels");outFilePath = docFilePath+".xml.rels";toText(dataMap,outFilePath,template);try {ZipInputStream zipInputStream = ZipUtils.wrapZipInputStream(new FileInputStream(new File(fileDirectory+File.separator+"report.zip")));//该zip文件是docx重命名后的压缩文件ZipOutputStream zipOutputStream = ZipUtils.wrapZipOutputStream(new FileOutputStream(new File(docFilePath+".docx")));File fileText = new File(docFilePath+".xml");File fileImg = new File(docFilePath+".xml.rels");ZipUtils.replaceItem(zipInputStream, zipOutputStream, new FileInputStream(fileText), new FileInputStream(fileImg),fileList);if(fileText.exists()){fileText.delete();}if(fileImg.exists()){fileImg.delete();}} catch (Exception e) {System.out.println(e.toString());}}/*** 生成pdf*/public static  void makePdfByXcode(String ftlPath,String docFilePath){try {XWPFDocument document=new XWPFDocument(new FileInputStream(new File(docFilePath+".docx")));File outFile=new File(docFilePath+".pdf");if(!outFile.getParentFile().exists()){outFile.getParentFile().mkdirs();}OutputStream out=new FileOutputStream(outFile);PdfOptions options= PdfOptions.getDefault();IFontProvider iFontProvider = new IFontProvider() {@Overridepublic Font getFont(String familyName, String encoding, float size, int style, Color color) {try {BaseFont bfChinese = null;if( OS.indexOf("linux")>=0){bfChinese =  BaseFont.createFont(ftlPath+"/font/msyh.ttf", BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED);}else{bfChinese =  BaseFont.createFont("C:/WINDOWS/Fonts/STSONG.TTF", BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED);}Font fontChinese = new Font(bfChinese, size, style, color);if (familyName != null)fontChinese.setFamily(familyName);return fontChinese;} catch (Exception e) {e.printStackTrace();return null;}}};options.fontProvider( iFontProvider );PdfConverter.getInstance().convert(document,out,options);}catch (  Exception e) {e.printStackTrace();}}}
public class ZipUtils {private static  String docText = "word/document.xml";//要替换的document.xml的位置private static  String imgName = "word/_rels/document.xml.rels"; //要替换的document.xml.rels的位置private static  String mediaName = "word/media/";//图片meida的位置/****@param zipInputStream zip文件的zip输入流*@param zipOutputStream 输出的zip输出流*@param docTextInputStream 替换后的document.xml文本*@param imgInputStream 替换后的document.xml.rels文本*@param fileList 需要压入meida的图片*/public static void replaceItem(ZipInputStream zipInputStream,ZipOutputStream zipOutputStream,InputStream docTextInputStream,InputStream imgInputStream, List<File> fileList){//if(null == zipInputStream){return;}if(null == zipOutputStream){return;}if(null == docTextInputStream){return;}boolean replaceMedia = false;//ZipEntry entryIn;try {while((entryIn = zipInputStream.getNextEntry())!=null){String entryName =  entryIn.getName();ZipEntry entryOut = new ZipEntry(entryName);// 只使用 namezipOutputStream.putNextEntry(entryOut);// 缓冲区byte [] buf = new byte[8*1024];int len;if(entryName.equals(docText)){// 使用替换流(替换文字内容)while((len = (docTextInputStream.read(buf))) > 0) {zipOutputStream.write(buf, 0, len);}}else if(entryName.equals( imgName)){// 使用替换流(替换图片)while((len = (imgInputStream.read(buf))) > 0) {zipOutputStream.write(buf, 0, len);}}else if(entryName.contains(mediaName)&&replaceMedia){}else if(entryName.contains(mediaName)&&!entryName.equals(mediaName)&&!replaceMedia){//将图片压缩到media目录中replaceMedia = true;if(entryName.contains("image1.png")){// 输出普通Zip流while((len = (zipInputStream.read(buf))) > 0) {zipOutputStream.write(buf, 0, len);}// 关闭此 entryzipOutputStream.closeEntry();}for(int i=0;i<fileList.size();i++){entryIn = new ZipEntry(mediaName+fileList.get(i).getName());zipOutputStream.putNextEntry(entryIn);FileInputStream in = null;try {in = new FileInputStream(fileList.get(i));while ((len = in.read(buf)) != -1){zipOutputStream.write(buf, 0, len);}// 关闭此 entryzipOutputStream.closeEntry();} catch (IOException e) {}finally {close(in);}}}else {// 输出普通Zip流while((len = (zipInputStream.read(buf))) > 0) {zipOutputStream.write(buf, 0, len);}}// 关闭此 entryzipOutputStream.closeEntry();}} catch (IOException e) {e.printStackTrace();}finally {//e.printStackTrace();close(docTextInputStream);close(zipInputStream);close(zipOutputStream);close(imgInputStream);}}/*** 包装输入流*/public static ZipInputStream wrapZipInputStream(InputStream inputStream){ZipInputStream zipInputStream = new ZipInputStream(inputStream);return zipInputStream;}/*** 包装输出流*/public static ZipOutputStream wrapZipOutputStream(OutputStream outputStream){ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream);return zipOutputStream;}private static void close(InputStream inputStream){if (null != inputStream){try {inputStream.close();} catch (IOException e) {e.printStackTrace();}}}private static void close(OutputStream outputStream){if (null != outputStream){try {outputStream.flush();outputStream.close();} catch (IOException e) {e.printStackTrace();}}}
}

加入以上class,按照自己指定的数据格式传入数据,则可生成docx和pdf文档

遇到的坑:
1、未理解docx,其实就是一个压缩zip文件,将其中需要替换的内容,替换后,重新生成一个docx文档就可以
2、docx如果有表格样式的动态内容循环,修改成模板后,重新压缩,修改后缀为docx不能打开,所以遇到表格样式的动态内容循环,尽量小心一些
3、资料太少,无处寻求帮组

第一次写博客哈,写的不好,希望大家多多提意见,希望对需要的朋友有帮组

如何使用freeMarker生成doc、docx文档相关推荐

  1. 第100篇博文纪念 | C# 根据数据库表结构生成DOC数据库文档

    一.目标 下图是我们要实现的目标: 二.实现 原理非常简单,首先制作样式模版,可以参照文章2,将排版好的Word另存为html,然后复制粘贴到aspx页面中,然后从数据库读取表以及字段信息,动态的插入 ...

  2. 在线预览doc,docx文档

    在线预览doc,docx文档 前言:上传成功以后的每个文档都能获取到所传文件的路径; 我这里是一个maven项目,需要在pom文件引入 <!-- 文件预览 --><dependenc ...

  3. Java web/springboot上传word/doc/docx文档(含图片)与HTML富文本导入/导出互相转换解析!附项目源码

    测试效果 先看下效果 文档内容如下: 上传 上传docx文档 查看解析内容 <html><head><style>p{margin-top:0pt;margin-b ...

  4. java用模板生成word(docx)文档(含动态表格)

    生成word思路 用WPS或者office编辑好word的样式,然后另存为word xml文档,将xml翻译为FreeMarker模板,最后用java来解析FreeMarker模板并输出Docx. 编 ...

  5. (doc, docx)文档合并的三种方法

    Word文档合并几种方式 通过com.spire.doc包 具体参考地址:https://www.e-iceblue.cn/spiredocforjavaoperating/merge-word-do ...

  6. java docx转pdf_java word/doc/docx文档转PDF 加水印

    本文实例讲述了java实现word文档转pdf并添加水印的方法.分享给大家供大家参考,具体如下: 前段时间,项目需要将上传的Word文档在浏览器浏览,思来想去,把word文档转成pdf就好了,于是乎研 ...

  7. 使用python-docx读取doc,docx文档

    API:    http://python-docx.readthedocs.io/en/latest/#api-documentation 将doc转为docx: from win32com imp ...

  8. 怎么解决缺少java.doc_java 生成doc帮助文档时出现的问题

    正在加载程序包com.csust.czj的源文件... 正在构造 Javadoc 信息... 标准 Doclet 版本1.7.0_03 正在构建所有程序包和类的树... 正在生成D:\EclipseP ...

  9. 根据mysql生成数据库设计文档,第100篇博文纪念 | C# 根据数据库表结构生成DOC数据库文档(1)...

    //==============================================================================作 者:农民伯伯//邮 箱:over14 ...

  10. 利用Freemarker模板生成doc或者docx文档(转载整理)

    可以直接看主要代码实现 doc作为模板文件生成指定格式的doc文件 实现逻辑 1.把作为模板的doc文件另存为xml文件 2.凡是需要填充的数据用${xxxx}替代 3.利用Template类将数据填 ...

最新文章

  1. yolov5检测完不显示框和标注
  2. PostgreSQL GIN multi-key search 优化
  3. java.lang.StackTraceElement类
  4. Verilog | HDL 音乐盒设计(代码类)
  5. linux下java命令行参数_Java调用Linux命令行
  6. 更换百度地图图标html,百度地图接口,自定义图标,点击切换图标
  7. 数组成员是函数java_在Laravel 5.6中调用数组上的成员函数links()
  8. centos7下安装pycharm
  9. 计算机基础备课计划,《计算机应用基础》教学计划备课讲稿.doc
  10. VS2012安装步骤
  11. 相关系数、相关指数和回归系数等概念含义
  12. 转本计算机知识普及软件,江苏专转本新政策的解读
  13. python keyboard backspace_键盘记录器在按backspace键时抛出错误(Python)
  14. PRN(20210421):Task-Free Continual Learning
  15. muti-thread fork
  16. 计算机翻译图片,扫描图片翻译在线翻译方法(纯干货~)
  17. 团购网站的现状和未来
  18. 用Mathematica实现各类积分图形区域绘制与积分计算及结果的快速检验方法(一)
  19. U盘安装Kali linux进行抓包破解或阻断wpa/wpa2加密WIFI
  20. GetDocument()

热门文章

  1. 《未来简史》—央美设计思维推荐书籍
  2. iPhone自动接听和拒接来电设置方法「苹果教程」
  3. 文本标注工具BRAT安装使用
  4. 2022Java的最流行的IDE工具
  5. 微信小程序和微信公众号的区别和优势
  6. php将中文转为英文,php将中文符号全部替换为英文符号
  7. 【codeforces】【Round#523D】TV shows
  8. (转)认识SAP SD销售模式之跨公司销售
  9. php石头剪刀布源码,剪刀石头布微信小程序配套源码
  10. JAVA 实现Excel导出下拉字符超出255字符(建议收藏!)