<dependency>
<!-- ALWAYS required. -->
<groupId>com.openhtmltopdf</groupId>
<artifactId>openhtmltopdf-core</artifactId>
<version>${openhtml.version}</version>
</dependency>
<dependency>
<!-- Required for PDF output. -->
<groupId>com.openhtmltopdf</groupId>
<artifactId>openhtmltopdf-pdfbox</artifactId>
<version>${openhtml.version}</version>
</dependency>
<dependency>
<!-- Required for image output only. -->
<groupId>com.openhtmltopdf</groupId>
<artifactId>openhtmltopdf-java2d</artifactId>
<version>${openhtml.version}</version>
</dependency>
<dependency>
<!-- Optional, leave out if you do not need right-to-left or bi-directional text support. -->
<groupId>com.openhtmltopdf</groupId>
<artifactId>openhtmltopdf-rtl-support</artifactId>
<version>${openhtml.version}</version>
</dependency>
<dependency>
<!-- Optional, leave out if you do not need HTML5 parsing support. -->
<groupId>com.openhtmltopdf</groupId>
<artifactId>openhtmltopdf-jsoup-dom-converter</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<!-- Optional, leave out if you do not need logging via slf4j. -->
<groupId>com.openhtmltopdf</groupId>
<artifactId>openhtmltopdf-slf4j</artifactId>
<version>${openhtml.version}</version>
</dependency>
<dependency>
<!-- Optional, leave out if you do not need SVG support. -->
<groupId>com.openhtmltopdf</groupId>
<artifactId>openhtmltopdf-svg-support</artifactId>
<version>${openhtml.version}</version>
</dependency>
<dependency>
<!-- Optional, leave out if you do not need MathML support. -->
<!-- Introduced in RC-13. -->
<groupId>com.openhtmltopdf</groupId>
<artifactId>openhtmltopdf-mathml-support</artifactId>
<version>${openhtml.version}</version>
</dependency>
其中 openhtml.version 为 1.0.10
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<style>
body {
font-family: simhei;
padding: 30px 20px 0;
}
.outTable{
margin-bottom: 20px;
}
table {
border-collapse: collapse;
table-layout: fixed;
width: 100%;
font-size: 13px;
/* margin: 20px 0px; */
text-align: center;
word-wrap: break-word;
page-break-inside:auto;
-fs-table-paginate:paginate;
border-spacing:0;
table-layout:fixed;
word-break:break-strict;
cellspacing:0;cellpadding:0;
border: solid 1px #ccc;
padding: 2px 2px;
}
tr {
page-break-inside:avoid;
page-break-after:auto;
height: 25px;
}
</style>
</head>
<body>
<h1>First Page</h1>
<div style="page-break-after:always;"></div>
<h1>Second Page</h1>
<div style="page-break-after:always;"></div>
<#if dataList ??>
<table class="outTable" border="1" cellspacing="0" cellpadding="0" width="100%">
<tr>
<td>日期</td>
<td>摘要</td>
<td>凭证种类</td>
<td>凭证号码</td>
<td>借方金额 </td>
<td>贷方金额</td>
<td>余额方向</td>
<td>余额</td>
</tr>
<#list dataList as item>
<tr>
<td>${(item.c1)!''}</td>
<td>${(item.c2)!''}</td>
<td>${(item.c3)!''}</td>
<td>${(item.c4)!''}</td>
<td>${(item.c5)!''}</td>
<td>${(item.c6)!''}</td>
<td>${(item.c7)!''}</td>
<td>${(item.c8)!''}</td>
</tr>
</#list>
</table>
</#if>
</body>
</html>
import com.openhtmltopdf.extend.FSSupplier;
import com.openhtmltopdf.outputdevice.helper.BaseRendererBuilder;
import com.openhtmltopdf.pdfboxout.PdfRendererBuilder;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.junit.jupiter.api.Test;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;
/**
* freemarker 转 pdf
*
* @author shanhy
* @date 2022-09-21 13:50
*/
public class OpenHtmlToPDFTest {
@Test
public void testConvert() throws IOException {
long start = System.currentTimeMillis();
String htmlContent = generateHtmlContent();
if (htmlContent == null || htmlContent.length() == 0)
return;
try (OutputStream os = Files.newOutputStream(Paths.get("D:\\Downloads\\html2pdf.pdf"))) { // 输出的pdf
PdfRendererBuilder builder = new PdfRendererBuilder();
builder.useFastMode();
// 下面这个useFont方法是指定字体文件,否则会导致pdf中文无法正常显示
// 第二个参数为引入的字体定义一个familyName,一般我们和文件名保持一致
// html页面style中的font-family必须和这里第二个参数定义的familyName一致
builder.useFont(new FSSupplier<InputStream>() {
@Override
public InputStream supply() {
try {
//指定 字体文件
return new FileInputStream("D:\\Downloads\\templates\\font\\simhei.ttf");
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return null;
}
}, "simhei", 400, BaseRendererBuilder.FontStyle.NORMAL, true);
// 第一个参数为html内容
// 第二个参数是一个全空的文件,文件必须存在,里面什么都没有但是后缀必须是htm,
// 其作用类似于一个空白画板,如果不添加这个参数或者置为null则html文件中的图片不能正常转换
builder.withHtmlContent(htmlContent, "D:\\Downloads\\templates\\root.htm");
builder.toStream(os);
builder.run();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("累计耗时=" + (System.currentTimeMillis() - start) + "ms");
}
@Test
public String generateHtmlContent() throws IOException {
String templateName = "test.ftl";
// 模板中的数据,实际运用从数据库中查询
Map<String, Object> data = new HashMap<>();
List<Map<String, String>> dataList = new ArrayList<>();
for (int i = 0; i < 10000; i++) {
Map<String, String> itemMap = new HashMap<>();
itemMap.put("c1", "20220927");
itemMap.put("c2", "跨行转入");
itemMap.put("c3", "999");
itemMap.put("c4", "13123123");
itemMap.put("c5", String.valueOf(1000 + i));
itemMap.put("c6", "0.00");
itemMap.put("c7", "贷");
itemMap.put("c8", "31312.00");
dataList.add(itemMap);
}
data.put("dataList", dataList);
// 创建一个FreeMarker实例, 负责管理FreeMarker模板的Configuration实例
Configuration cfg = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
// 指定FreeMarker模板文件的位置
cfg.setDirectoryForTemplateLoading(Paths.get("D:\\Downloads\\templates").toFile());
// cfg.setClassForTemplateLoading(OpenHtmlToPDFTest.class,"/templates");
try (StringWriter writer = new StringWriter()) {
// 设置模板的编码格式
cfg.setEncoding(Locale.CHINA, "UTF-8");
// 获取模板文件
Template template = cfg.getTemplate(templateName, "UTF-8");
// 将数据输出到html中
template.process(data, writer);
return writer.toString();
} catch (TemplateException e) {
e.printStackTrace();
}
return null;
}
}
测试时,我使用宋体字体文件 simsun.ttc ,发现不起作用,生成的 pdf 文件中文为 ###,具体原因未进一步排查
(END)