问题描述:

最早试过了xml模板生成word,虽然文件格式保留的多,但是这种模板生成的word转html,用单纯的poi中的XWPFDocument、HWPFDocument是有问题的,因为word本质上还是xml,xml转html,poi是暂时不支持的,而且,除了上述的问题外,xml模板的语言很少有java去学习,一旦涉及到模板的调整,一般都是花费很大力气都很难改成功的,基于上述的情况,我并没有采用这种方法。

后来试过了zip中提取document.xml的形式,再将动态的xml最后压缩进zip源文件中,但是发现,维护成本加大,需要一个word和一个xml来进行维护,调整格式总是需要兼顾word模板,而且word转html还是有poi出现的问题,虽然可以生成docx格式的文件,但是还是无法应对需求

当然用Jacob也是可以的,不过因为Jacob的要求需要在windows系统上,所以只能pass掉

为了实现ftl转word和html,转化之后,在富文本中进行编辑修改,保存再次转化成word,实现文件的在线编辑和预览功能,采用了如下的操作方法

1、生成html模板

原始的word,通过文件->另存为

生成的文件为格式并不是utf-8,需要转码一下,这里直接用notepad++菜单栏中的Encoding直接转为utf-8编码即可

删除掉图片中绿色部分的xml代码,且修改<meta http-equiv=Content-Type  content="text/html; charset=gb2312" >中的charset为utf-8,且文件名称后缀修改为.ftl格式

需要动态的内容可以将ftl的内容动态化,参考freemark的语法

2、springboot配置freemark解析

需要引入的jar:

<!-- freemarker -->
<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>

在application.properties文件中配置freemarker 

#freemarker
spring.freemarker.template-loader-path=classpath:/templates/
spring.freemarker.charset=utf-8
spring.freemarker.cache=false
spring.freemarker.suffix=.ftl

项目如果启动不起来,可能是spring-boot-starter-freemarker中引入的jar出现了冲突,重复引入,需要排除重复的jar,需要注意

3、ftl生成html和word

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.StringWriter;
import java.util.Map;
import java.io.FileOutputStream;

import freemarker.template.Configuration;
import freemarker.template.Template;
import lombok.extern.slf4j.Slf4j;
import org.apachemons.lang.StringEscapeUtils;
import org.apache.poi.poifs.filesystem.DirectoryEntry;
import org.apache.poi.poifs.filesystem.DocumentEntry;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.springframework.web.util.HtmlUtils;

/**
 * @FileNName: WordUtil
 * @Description: word操作工具类
 * @Author: guoxingliang
 * @Create: 2019-08-16 17:08
 * @Copyright: (c)2018年 ***公司
 */
@Slf4j
public class WordUtil {

    private WordUtil() {}

    /**
     * @param content      页面内容
     * @param filePath     文件生成的目标路径,例如:D:/wordFile/
     * @param fileName     生成的文件名称,例如:test.doc
     * @Desc:生成word文件
     * @Author:guoxingliang
     * @Date:2018-8-22下午05:33:42
     */
    public static void createWord(String content, String filePath, String fileName) {
        try {
            //输出文件
            File outFile = new File(filePath + File.separator + fileName);
            //如果输出目标文件夹不存在,则创建
            if (!outFile.getParentFile().exists()) {
                outFile.getParentFile().mkdirs();
            }
            content = HtmlUtils.htmlUnescape(StringEscapeUtils.unescapeHtml(content));
            //格式化html
            byte[] by = content.getBytes();
            ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(by);
            POIFSFileSystem poifsFileSystem = new POIFSFileSystem();
            DirectoryEntry directory = poifsFileSystem.getRoot();
            DocumentEntry documentEntry = directory.createDocument("WordDocument", byteArrayInputStream);
            FileOutputStream fileOutputStream = new FileOutputStream(filePath + File.separator + fileName);
            poifsFileSystem.writeFilesystem(fileOutputStream);
            byteArrayInputStream.close();
            fileOutputStream.close();
        } catch (Exception e) {
            log.error("word create fail, exception:", e);
        }
    }

    /**
     * @param dataMap      word中需要展示的动态数据,用map集合来保存
     * @param templateName word模板名称,例如:test.ftl
     * @Desc:生成html文件
     * @Author:guoxingliang
     * @Date:2018-8-22下午05:33:42
     */
    public static String createHtml(Map dataMap, String templateName) {
        try {
            //创建配置实例 
            Configuration configuration = new Configuration();
            //设置编码
            configuration.setDefaultEncoding("UTF-8");
            //ftl模板文件统一放至 com.lun.template 包下面
            configuration.setClassForTemplateLoading(WordUtil.class, "/templates");
            //获取模板 
            Template template = configuration.getTemplate(templateName);
            //将模板和数据模型合并生成文件
            StringWriter stringWriter = new StringWriter();
            //生成html
            template.process(dataMap, stringWriter);
            return stringWriter.toString();
        } catch (Exception e) {
            log.error("html create fail, exception:", e);
        }
        return null;
    }
}

4、html字符串转码

由于html字符串中存在很多的特殊字符,比如说\t,\n,\r以及空格回车双引号,为了好处理,这里我进行了一些代码转化

加密:
HtmlConversionUtil.replaceBlank(StringEscapeUtils.escapeHtml(WordUtil.createHtml(dataMap, "agreementJurisdiction.ftl")));
解密:
StringEscapeUtils.unescapeHtml(htmlStr);

replaceBlank方法:
public static String replaceBlank(String str) {
    String dest = "";
    if (str!=null) {
       Pattern p = Patternpile("\t|\r|\n");
       Matcher m = p.matcher(str);
       dest = m.replaceAll("");
    }
    return dest;
}

<!-- StringEscapeUtils所需要引入的依赖 -->
<dependency>
     <groupId>commons-lang</groupId>
     <artifactId>commons-lang</artifactId>
     <version>2.5</version>
</dependency>

 

注:上述方法虽然可以实现功能,但是暂未涉及到图片、页眉页脚等复杂格式的支持。

更多推荐

java关于ftl模板生成html以及word(实现在线预览、编辑功能)