题外话:帖子百度搜了半天多,没找到合适的,如果你需求差不多,可以省很多时间
需求
每个主体的信息自然是不同的,需要基于word模板,填充主体的数据,浏览器导出PDF(PDF有2页)。
需求模板如下
实现思路
freemarker+spire.doc.free
数据库读取相关数据->freemarker语法渲染->spire.doc.free转为PDF流->写入response流导出
说明:
spire.doc:第三方收费包,有个免费包:spire.doc.free
不采用其他jar包的原因,要么收费,要么格式错乱
实现步骤
1、编辑word,需要填充的字段用 ${xxx}
2、word另存为xml格式(不重名为.ftl也是可以的)
3、resources目录下创建templates文件夹,存放xml文件
4、 ①处理xml文件 每个$变量后添加 "?if_exists"
作用:如果不加,该值为空会报错。
②检查下${} 大括号内是否有xml的代码!有的会带
5、pom引用
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.32</version>
</dependency>
<dependency>
<groupId>com.bestpay.spiredoc</groupId>
<artifactId>spire.doc.free</artifactId>
<version>5.2.0</version>
</dependency>
6、后端主要代码
//引用的包
import com.spire.doc.Document;
import com.spire.doc.FileFormat;
//查询数据省略
//保存要导出的数据
Map<String, Object> dataMap = new HashMap<>();
dataMap.put("custId", "客户号");
dataMap.put("custName", "客户名称");
//导出pdf
//模板存放路径
String templatesPath = "/templates";
FreemarkerFtlUtil freemarkerFtlUtil = new FreemarkerFtlUtil();
ByteArrayOutputStream outputStream = freemarkerFtlUtil.writeToByteArrayOutputStream(dataMap, templatesPath, tempName);
response.setContentType("application/pdf;charset=utf-8");
response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode(dueDiLiGenceVO.getFileName() + ".pdf", "UTF8"));
//写出到响应流
Document document = new Document(new ByteArrayInputStream(outputStream.toByteArray()));
document.saveToStream(response.getOutputStream(), FileFormat.PDF);
document.close();
import freemarker.template.Configuration;
import freemarker.template.Template;
import java.io.ByteArrayOutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.Map;
/**
* @Author
* @Description freemarker操作 ftl文件工具类
* @Param
* @return
**/
public class FreemarkerFtlUtil {
//将数据写入到ftl模板中,并转为字节输出流
public ByteArrayOutputStream writeToByteArrayOutputStream(Map<String, Object> dataMap, String templatePath,
String templateName) throws Exception {
Configuration configuration = new Configuration(Configuration.getVersion());
configuration.setClassForTemplateLoading(getClass(), templatePath);
//下面方式Linux环境报错
// configuration.setDirectoryForTemplateLoading(new File(templatePath));
configuration.setDefaultEncoding("utf-8");
//写出doc到流
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Writer out = new OutputStreamWriter(baos, "UTF-8");
Template template = configuration.getTemplate(templateName);
template.process(dataMap, out);
out.flush();
return baos;
}
}
坑
1、关于spire.doc.free,一定需要用5.2.0,一定需要用5.2.0,一定需要用5.2.0!
5.1.0版本会报错!
2、freemarker加载模板的路径问题,按照上述操作,不会出现读不到的问题。