当前位置: 首页 > 工具软件 > openhtmltopdf > 使用案例 >

freemarker 和 openhtmltopdf 生成 pdf Demo

咸亦
2023-12-01

1、引入依赖


        <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

2、模板文件 test.ftl

<!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>

3、完整Java测试代码

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)

 类似资料: