思路一:直接导出pdf
使用freemarker和itext把html转pdf,存在中文乱码,宋体不识别,需下载simsun.ttc字体,空白占位符不识别等等问题,对前端依赖性较大,不推荐;
适用范围:业务生成的 pdf 是具有固定格式或者模板的文字及其图片等内容,使用模板,只需要将不一致的地方改成文本域,然后进行文字填充就可以了;如果涉及的业务不能有模块化可以提取出来东西,从开头一步一步去绘画。
参考链接:JAVA 使用Itext模板生成pdf,解决图片插入,文本域超出字体缩放,半自动换行
java根据模板生成pdf文件并导出
缺点:
超出文本域的部分的文字(若不设置自动调整文字大小)则会不显示,无法自动分页。(暂未找到解决方案)
思路二:先导出word再转成pdf :spire.doc.free + freemarker
1)导出word
-
FreemarkerFreemarker 将数据填入 .ftl 模板导出 word(.doc/.docx)
(注意:需要循环展示的内容还需要在xml文件中处理)FreeMarker 是一个用Java语言编写的模板引擎,它基于模板输出文本。FreeMarker 与 Web 容器无关,即在Web运行时,它并不知道 Servlet 或 HTTP。它不仅可以用作表现层的实现技术,而且还可以用于生成XML,JSP或Java 等。
Java 程序准备的数据来显示(比如 SQL 查询),FreeMarker 仅仅使用模板生成文本页面来呈现已经准备好的数据。
Freemarker 的使用步骤
1)、创建一个Configuration对象,直接new一个对象。构造方法的参数就是freemarker对于的版本号;
2)、设置模板文件所在的路径;
3)、设置模板文件使用的字符集。一般就是UTF-8;
4)、加载一个模板,创建一个模板对象;
5)、创建一个模板使用的数据集,可以是pojo也可以是map。一般是Map;
6)、创建一个Writer对象,一般创建一FileWriter对象,指定生成的文件名;
7)、调用模板对象的process方法输出文件;
8)、关闭流;
public void exportWord(HttpServletRequest request, HttpServletResponse response, String fileName , String templeteName, Object dataModel){
//1. 创建一个Configuration对象
Configuration configuration=new Configuration();
//设置模板文件的字符集
configuration.setDefaultEncoding("utf-8");
configuration.setEncoding(Locale.getDefault(),"utf-8");
try {
configuration.setClassicCompatible(true);//处理dataModel中如果为null的情况
//2. 设置模板文件所在的路径的目录
// configuration.setDirectoryForTemplateLoading(new File(CommonUtil.getTempletePath()+"/template/"));
//保证本地运行找得到模板文件,jar包运行能找到得到模板文件
configuration.setClassForTemplateLoading(this.getClass(),"/template");
configuration.setTemplateLoader(new ClassTemplateLoader(this.getClass(),"/template"));
//3. 首先创建模板文件,再加载模板文件 模板文件的后缀官方统一的标准是.ftl 其实任何类型都行
Template t=configuration.getTemplate(templeteName,"utf-8");// 可以是<相对路径>,也可以是<绝对路径>
//设置了HTTP响应的内容类型为Microsoft Word文档(application/msword:word文档),并且指定了字符集为UTF-8。
response.setContentType("application/msword; charset=UTF-8");// application/x-download
//设置了HTTP响应的附加头信息Content-Disposition,其内容为'文件下载',并且文件名是经过编码后的文件名(包含后缀.doc),即fileName+".doc"。这表示服务器将要发送一个文件下载请求,用户需要在浏览器中点击下载链接才能获取到文件。
response.setHeader("Content-Disposition", "attachment; "
+ encodeFileName(request, fileName+".doc"));
//这个地方不能使用FileWriter因为需要指定编码类型否则生成的Word文档会因为有无法识别的编码而无法打开
OutputStream outputStream = response.getOutputStream();
Writer out=new OutputStreamWriter(outputStream);
//调用模板对象的process方法,执行输出文件。
t.process(dataModel, out);
outputStream.close();
out.close();
} catch (IOException | TemplateException e) {
e.printStackTrace();
}
1)导出对象字段有为null时,报错,加上“configuration.setClassicCompatible(true);”
2)idea运行能正常导出,jar运行不能找到模板,代码中给出了解决
3)cmd运行jar,能正常导出word,但是打开错误。
经过测试发现导出word文档乱码,发现是是cmd默认编码问题,在cmd执行时加上:
start javaw -Dfile.encoding=utf-8 -jar xxx.jar
参考链接:SpringBoot整合Freemarker导出word文档表格
freemarker导出Word,文本,可循环表格,合并单元格,可循环图片,目录更新(一)
缺点:
导出的 .doc / .docx 实际上是 xml 文件,用办公软件能正常打开使用。但是转 PDF 的时候发现转不成功。转过之后的 PDF 显示的不是 word 的格式字符,而是像 xml 文件的标签及字符。
Freemarker 结合 .docx 格式的本质将数据填入 .docx 里面的 document.xml 文件导出 .docx
参考链接:
freemarker动态生成word并将生成的word转为PDF
优点:
可转换为 pdf
相关错误:
A. Date 格式的数据传输报错!
解决方案:
${(initialTime?string("yyyy-MM-dd HH:mm:ss"))!}
附:
a. 循环行及表单行是否显示功能参考链接:
SpringBoot整合Freemarker导出word文档表格
freemarker合并单元格,if、else标签的使用,null、空字符串处理
-
dock4j结合 .docx 格式的本质将数据填入 .docx 里面的 document.xml 文件导出 .docx
docx4j 中模板的使用
-
POI
-
Aspose.word(需要license)
2)word转pdf
思路一:
将目标word文件另存为xml文件,将里面的需要动态生成的内容用freemarker的表达式${}替换.
用freemarker生成word的工具类,动态生成word. 这样生成的word实际上是xml文件,用办公软件能正常打开使用.
但是转PDF的时候发现转不成功.转过之后的PDF显示的不是word的格式字符,而是像xml文件的标签及字符,失败!
-
dock4j将.docx转pdf
- 使用 docxToPdf() 将 .docx 文件转换为 .pdf 时,中文的可以顺利换行,但是一连串的英文就会超出表格,无法自动换行。
-
Spire.Doc 实现 word (.doc / .docx)转 pdf
有付费版和免费版,免费版仅支持三页内的 word 转 pdf
-
aspose.word 将 word 转 pdf (需要license)