使⽤freemarker+itextpdf通过HTML模版导出PDF
⽀持作者
最便宜的卫⽣纸
⼀简介
因公司业务需求需要做⼀个通过模版导出PDF的功能,模版是word⽂档,模版中包含图⽚,⽂字,⽔印,分页。遇到这种没做过的功能,没什么可说的,直接问度娘。结果度娘给不了我想要的,只好去github上下了⼀些相关的项⽬,通过筛选和实验终于到了不错的代码,但是在使⽤过程中也是踩了⽆数坑,随记录下来。
⼆思路
通过模版导出PDF的⽅法有很多,但是思路都⼤致相同,总结起来就是 1 渲染模版 2 导出模版。以为之
前使⽤过freemarker,所以我这⾥渲染模版的技术⽤的是freemarker,然后在使⽤itextpdf将渲染好的模版导出。
三踩过的坑
1 Win下中⽂不显⽰
2 图⽚不显⽰
3 Linux下中⽂不显⽰
4 图⽚样式跑偏
5 分页加⽔印
四上代码
4.1 准备⼯作
4.11⾸先准备好⼀个word模版,如下图所⽰
4.1.2 将word模版通过wps或其他⼯具另存为  转为HTML模版.
转为html后 ${}会被 分开,通过在线格式化⼯具排版HTML,将${}之间多余的代码删掉,重新恢复到${},批量操作即可.
4.1.3 新建⼀个ftl⽂件,将HTML代码拷贝进去 如下图所⽰
4.1.4 maven坐标
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.23</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.4.2</version>
</dependency>
<dependency>
<groupId>l</groupId>
<artifactId>xmlworker</artifactId>
<version>5.4.1</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
<dependency>
<groupId>org.xhtmlrenderer</groupId>
<artifactId>flying-saucer-pdf</artifactId>
<version>9.0.3</version>
</dependency>
4.2 写代码新建⼀个PDF⼯具类
4.2.1 第⼀步 渲染模版 代码如下
/
/获取模板并填充数据
public static String getContent(String fileName,Object data) throws Exception{
// 创建⼀个Configuration对象
Configuration configuration = new Version());
Configuration config = new Version());//FreeMarker配置
// 告诉config对象模板⽂件存放的路径。
configuration.setDirectoryForTemplateLoading(new File(ClassLoader().getResource("templates/").getPath()));          // 设置config的默认字符集。⼀般是utf-8
configuration.setDefaultEncoding("utf-8");
//从config对象中获得模板对象。需要制定⼀个模板⽂件的名字。
Template template = Template(fileName+".ftl");
StringWriter writer = new StringWriter();
//模版和数据匹配
template.process(data, writer);
writer.flush();
String html = String();
return getImgs(html);
}
4.2.2 第⼆步 替换模版中的图⽚路径 代码如下
//替换html中的图⽚路径
private static String getImgs(String content) {
String img = "";
Pattern p_image;
Matcher m_image;
String str = "";
String[] images = null;
String regEx_img = "(<img.*src\\s*=\\s*(.*?)[^>]*?>)";
html document是什么p_image = Patternpile(regEx_img, Pattern.CASE_INSENSITIVE);
m_image = p_image.matcher(content);
if(m_image!=null){
while (m_image.find()) {
img = up();
Matcher m = Patternpile("src\\s*=\\s*\"?(.*?)(\"|>|\\s+)")
.
matcher(img);
if(m!=null){
while (m.find()) {
String tempSelected = m.group(1);
str = tempSelected;
String classpath= RootPath();
String ulr=classpath.substring(5,classpath.length());
place(str,ulr+"templates/"+str);
}
}
}
}
return content;
}
⼯具类 PathUtil
/**
* @author:change
* @description:获取绝对路径
* @date:2018/6/28 0028
*/
public class PathUtil {
static String path1;
static String download;
public static String getRootPath() {
String line = File.separator;
String path = Thread.currentThread().getContextClassLoader().getResource("").toString();        //windows下
if ("\\".equals(line)) {
/*            path = place("/", "\\");  // 将/换成\\*/
path1 = path;
}
//linux下
if ("/".equals(line)) {
path = place("\\", "/");
path1 = path;
}
return path1;
}
public static void main(String[] args) {
System.out.println(getRootPath());
System.out.println(ClassLoader().getResource("").getPath());
}
}
4.2.3 设置pdf字符集 代码如下
/**
* 设置字符集
*/
public static class MyFontsProvider extends XMLWorkerFontProvider {
public MyFontsProvider(){
super(null, null);
}
@Override
public Font getFont(final String fontname, String encoding, float size, final int style) {            String fntnames = fontname;
Font FontChinese = null;
if (fntnames == null) {
fntnames = "宋体";
}
if (size == 0) {
size = 4;
}
try{
BaseFont bfChinese = ateFont("STSong-Light",
"UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
FontChinese = new Font(bfChinese, 12, Font.NORMAL);
}catch (Exception e){
e.printStackTrace();
}
if(FontChinese==null){
FontChinese = Font(fntnames, encoding, size, style);
}
return FontChinese;
}
}
4.2.4 ⽣产PDF并下载 代码如下

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。