HTML及FTL文件转换为PDF的实现方式

业务场景

当我们遇到表格数据(类似于word中设计的表格)需要动态的填充数据,而这个数据是从数据库等地方作为对象获取的,这个时候我们需要使用特定的技术去实现动态数据填充以及html页面转换pdf的实现。当我们遇到类似的业务场景的时候,可以参考这篇文章去实现。

第一步:导入依赖

java 复制代码
    <properties>
        <java.version>1.8</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <spring-boot.version>2.3.12.RELEASE</spring-boot.version>
        <servlet>3.1.0</servlet>
        <freemarker>2.3.22</freemarker>
        <flying-saucer>9.1.12</flying-saucer>
        <commons-lang3.version>3.12.0</commons-lang3.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>${servlet}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>${freemarker}</version>
        </dependency>
        <dependency>
            <groupId>org.xhtmlrenderer</groupId>
            <artifactId>flying-saucer-pdf</artifactId>
            <version>${flying-saucer}</version>
        </dependency>

        <!-- log4j必需 -->
        <!-- https://mvnrepository.com/artifact/log4j/log4j -->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>2.0.9</version>
        </dependency>


        <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.46</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

主要是前三个依赖,剩余的依赖是对日志记录的使用,Freemarker依赖是Java中对模板和数据进行整合的使用,flying-saucer-pdf是针对pdf生成需要。

第二步:编写填充数据的方法以及生成pdf方法

java 复制代码
package com.xiaobai.common;
 
 
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.StringWriter;
import java.util.Locale;
 
 
import javax.servlet.http.HttpServletResponse;
 
 
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xhtmlrenderer.pdf.ITextRenderer;
 
 
import com.lowagie.text.DocumentException;
import com.lowagie.text.pdf.BaseFont;
 
 
import freemarker.core.ParseException;
import freemarker.template.Configuration;
import freemarker.template.MalformedTemplateNameException;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import freemarker.template.TemplateNotFoundException;
 
 
/**
 * Description: PDF生成工具类
 * @author xiaobai
 */
@SuppressWarnings("all")
public class PDFUtil {
	
	private static final Logger logger = LoggerFactory.getLogger(PDFUtil.class);	
	
	/**
	 * Description: 生成PDF到文件
	 * @param ftlPath  模板文件路径(不含文件名)
	 * @param ftlName  模板文件(不含路径)
	 * @param imageDiskPath 图片的磁盘路径
	 * @param data 数据 (填到模板上的数据)
	 * @param outputFile 目标文件(全路径名称)
	 * @throws Exception
	 */
	public static void generateToFile(String ftlPath, String ftlName, String imageDiskPath, Object data,String outputFile) throws Exception {
	        OutputStream out = null;
		ITextRenderer render = null;
		try {
			String html = getPdfContent(ftlPath, ftlName, data);	//组装模板和数据生成html串
			out = new FileOutputStream(outputFile);
			render = getRender();
			render.setDocumentFromString(html);		//此处抛异常
			if (imageDiskPath != null && !imageDiskPath.equals("")) {
				// html中如果有图片,图片的路径则使用这里设置的路径的相对路径,这个是作为根路径
				render.getSharedContext().setBaseURL("file:/" + imageDiskPath);
			}
			render.layout();
			render.createPDF(out);
			render.finishPDF();
			render = null;
		} catch (Exception e) {
			logger.error("Exception:",e);
			throw e;
		}finally{
			if (out != null) {
			        try {
					out.close();
				} catch (IOException e) {
					logger.error("Exception:",e);
					throw e;
				}
			}
		}
	}
 
 
	/**
	 * 生成PDF到输出流中(ServletOutputStream用于下载PDF)
	 * 
	 * @param ftlPath
	 *            ftl模板文件的路径(不含文件名)
	 * @param ftlName
	 *            ftl模板文件的名称(不含路径)
	 * @param imageDiskPath
	 *            如果PDF中要求图片,那么需要传入图片所在位置的磁盘路径
	 * @param data
	 *            输入到FTL中的数据
	 * @param response
	 *            HttpServletResponse
	 * @return
	 * @throws TemplateNotFoundException
	 * @throws MalformedTemplateNameException
	 * @throws ParseException
	 * @throws IOException
	 * @throws TemplateException
	 * @throws DocumentException
	 */
	public static OutputStream generateToServletOutputStream(String ftlPath, String ftlName, String imageDiskPath,
			Object data, HttpServletResponse response) throws Exception {
		String html = getPdfContent(ftlPath, ftlName, data);
		OutputStream out = null;
		ITextRenderer render = null;
		out = response.getOutputStream();
		render = getRender();
		render.setDocumentFromString(html);
		if (imageDiskPath != null && !imageDiskPath.equals("")) {
			// html中如果有图片,图片的路径则使用这里设置的路径的相对路径,这个是作为根路径
			render.getSharedContext().setBaseURL("file:/" + imageDiskPath);
		}
		render.layout();
		render.createPDF(out);
		render.finishPDF();
		render = null;
		return out;
	}
	
	public static ITextRenderer getRender() throws DocumentException, IOException {
		ITextRenderer render = new ITextRenderer();
		String path = getPath();
		// 添加字体,以支持中文
		render.getFontResolver().addFont(path + "fonts/ARIALUNI.TTF", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
		render.getFontResolver().addFont(path + "fonts/SIMSUN.TTC", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
		return render;
	}
 
 
	// 获取要写入PDF的内容
	public static String getPdfContent(String ftlPath, String ftlName, Object o) throws Exception {
		return useTemplate(ftlPath, ftlName, o);
	}
 
 
	// 使用freemarker得到html内容
	public static String useTemplate(String ftlPath, String ftlName, Object o) throws Exception {
		String html = null;
		Template tpl = getFreemarkerConfig(ftlPath).getTemplate(ftlName);
		tpl.setEncoding("UTF-8");
		StringWriter writer = new StringWriter();
		tpl.process(o, writer);
		writer.flush();
		html = writer.toString();
		return html;
	}
 
 
	/**
	 * 获取Freemarker配置
	 * 
	 * @param templatePath
	 * @return
	 * @throws IOException
	 */
	private static Configuration getFreemarkerConfig(String templatePath) throws IOException {
		Configuration config = new Configuration();
		config.setDirectoryForTemplateLoading(new File(templatePath));
		config.setEncoding(Locale.CHINA, "utf-8");
		return config;
	}
 
 
	/**
	 * 获取类项目根路径
	 */
	public static String getPath() {
		//return PDFUtil.class.getResource("").getPath().substring(1);	//返回类路径(当前类所在的路径)
		return PDFUtil.class.getResource("/").getPath().substring(1);	//返回项目根路径(编译之后的根路径)
	}
}

第三步:编写ftl文件

java 复制代码
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    	<meta http-equiv="Content-Style-Type" content="text/css"/>
		<title>文档标题</title>
		<style type="text/css">	
			body{
				margin: 0 45px;
				font-family: Arial Unicode MS;
				font-size: 12px;
				color: #000;
			}
			.document_body h1 , 
			.document_body h2 , 
			.document_body h3 , 
			.document_body h4 , 
			.document_body h5 , 
			.document_body h6 ,
			.document_body p{
				width:100%;
				height: 100%;
				color: #000;
				margin: 0;
				font-weight: normal;
				text-indent: 0;
			}
			.document_body .logo_position{
				width: 20%;
				position: absolute;
				top: 20px;
				left: 0;
			}
			.document_body .logo_position >img{width: 100%;}
			.document_body{
				width: 100%;    /*可以修改此处的宽度百分比来适应页面大小*/
				padding-top: 40px;
				margin: 0 auto;
				position: relative;
 
			}
			.document_body p{
				text-align: justify;
				text-justify: inter-word;			
			}
			.document_head{margin-bottom: 10px;}
			.document_head .heading{text-align: right;}
			.document_head .heading h1{
				font-size: 20px;
				line-height: 36px;
				text-align: right;
				font-weight: bold;
			}
			.document_head .heading h6{
				text-align: right;
				font-weight: bold;
				font-size: 12px;
			}
			table{
				width: 100%;
				text-align: left;
				margin-bottom: 10px;
			}
			table .table_title{
				background: #999;
				color: #fff;
				font-size: 14px;
				text-align: center;
				font-weight: bold;
			}
			table .strong_area{
				background: #FFEC00;
			}
			span.line_input{
				display: inline-block;
				border-bottom: 1px solid #000;
				padding: 0 6px;
				margin-left: 2px;
			}
			.document_body .document_main .blank{font-family: "Times New Roman"}
			.sign_area{
				margin-top: 10px;
			}
			.sign_area > div{
				float: left;
			}
			.sign_area > div >b{
				display: block;
				height: 30px;
				font-weight: normal;
			}
			strong{
				font-weight: bold;
				color: red;
			}
			.explain_text p{line-height: 1.5}
			.explain_text h5{font-weight: bold;}
			.clear{clear: both;}
			.mr10{margin-right: 10px;}
			.link a{
				font-weight: bold;
				color: #000;
				font-size: 13px;
			}
			.document_body .side_tips{
				position: absolute;
				top:400px;
				right: -18px;
				width: 10px;
			}
		</style>
	</head>
	<body>
		<!--文档start-->
			<div class="document_body">
				<div class="document_head">
					<div class="logo_position"><img src="logo_269_48.png" alt="logo"/></div>
					<div class="heading">
						<h1>文档标题</h1>
						<h6>提示:警惕洗钱风险,保护您的权益</h6>
					</div>				
				</div>
				<div class="document_main">				
					<table cellspacing="0" border="1" cellpadding="4">
						<tr>
							<td colspan="3" class="table_title">账 户 信 息 1</td>
						</tr>
						<tr class="strong_area">
							<td align="center">存款人名称</td>
							<td colspan="2">${data.remark1}</td>
						</tr>
						<tr>
							<td align="center">办公地址</td>
							<td colspan="2">
							<#if data.remark2 == "01">
							<input type="checkbox" checked="true"/><label class="mr10">同注册地址</label>或 <input type="checkbox"/><label>其它:</label><span class="line_input">  </span>省/区/直辖市<span class="line_input">  </span>市 <span class="line_input">  </span> 区/县 <span class="line_input">  </span>
							<#else>
							<input type="checkbox"/><label class="mr10">同注册地址</label>或 <input type="checkbox" checked="true"/><label>其它:</label><span class="line_input">${data.remark3}</span>省/区/直辖市<span class="line_input">${data.remark4}</span>市 <span class="line_input">${data.remark5}</span> 区/县 <span class="line_input">${data.remark6}</span>
							</#if>
							</td>
						</tr>
						<tr>
							<td align="center">邮寄地址</td>
							<td colspan="2">
							<#if data.remark7 == "01">
							<input type="checkbox" checked="true"/><label class="mr10">同注册地址</label>或 1.<input type="checkbox"/><label class="mr10">同办公地址</label>  2.<input type="checkbox"/><label>其它:</label><span class="line_input">  </span>省/区/直辖市<span class="line_input">  </span>市 <span class="line_input">  </span> 区/县 <span class="line_input">  </span>
							<#elseif data.remark7 == "02">
							<input type="checkbox"/><label class="mr10">同注册地址</label>或 1.<input type="checkbox" checked="true"/><label class="mr10">同办公地址</label>  2.<input type="checkbox"/><label>其它:</label><span class="line_input">  </span>省/区/直辖市<span class="line_input">  </span>市 <span class="line_input">  </span> 区/县 <span class="line_input">  </span>
							<#else>
							<input type="checkbox"/><label class="mr10">同注册地址</label>或 1.<input type="checkbox"/><label class="mr10">同办公地址</label>  2.<input type="checkbox" checked="true"/><label>其它:</label><span class="line_input">${data.remark8}</span>省/区/直辖市<span class="line_input">${data.remark9}</span>市 <span class="line_input">${data.remark10}</span> 区/县 <span class="line_input">${data.remark11}</span>
							</#if>
							</td>
						</tr>
						<tr>
							<td rowspan="3" align="center">联系信息</td>
							<td>
							<#if data.remark12 == "01">
							<input type="checkbox" checked="true"/><label class="mr10">法定代表人</label>或<br/><input type="checkbox"/><label>单位负责人</label>
							<#else>
							<input type="checkbox"/><label class="mr10">法定代表人</label>或<br/><input type="checkbox" checked="true"/><label>单位负责人</label>
							</#if>
							</td>
							<td>办公电话:区号<span class="line_input">${data.remark13}</span>直线<span class="line_input">${data.remark14}</span>分机<span class="line_input">${data.remark15}</span><br/>移动电话:<span class="line_input">${data.remark16}</span></td>
						</tr>
						<tr>
							<td class="strong_area" align="center">财务负责人</td>
							<td>姓名:<span class="line_input mr10">${data.remark17}</span>办公电话:区 号<span class="line_input">${data.remark18}</span>直线<span class="line_input">${data.remark19}</span>分机<span class="line_input">${data.remark20}</span><br/>移动电话:<span class="line_input mr10">${data.remark21}</span>电子邮箱:<span class="line_input">${data.remark22}</span></td>
						</tr>
						<tr class="strong_area">
							<td align="center">财务经办人员</td>
							<td>姓名:<span class="line_input mr10">${data.remark23}</span>办公电话:区 号<span class="line_input">${data.remark24}</span>直线<span class="line_input">${data.remark25}</span>分机<span class="line_input">${data.remark26}</span><br/>移动电话:<span class="line_input">${data.remark27}</span></td>
						</tr>
						<tr>
							<td rowspan="2" align="center">账户种类</td>
							<td align="center">人民币</td>
							<td>
							<#if data.remark28 == "01">
								1.<input type="checkbox" checked="true"/><label class="mr10">定期账户</label>2.<input type="checkbox"/><label class="mr10">基本户</label>3.<input type="checkbox"/><label>一般户且用于:</label>
									<input type="checkbox"/><label class="mr10">结算</label><input type="checkbox"/><label class="mr10">贷款</label>或 <input type="checkbox"/><label>其它:</label>	<span class="line_input">    </span><br/>
								4.<input type="checkbox"/><label class="mr10">临时户</label>5.<input type="checkbox"/><label>专用户且账户资金性质为:</label><span class="line_input mr10"> </span>6.<input type="checkbox"/><label>NRA账户且国家代码为:</label><span class="line_input mr10"> </span>
							<#elseif data.remark28 == "02">
								1.<input type="checkbox"/><label class="mr10">定期账户</label>2.<input type="checkbox" checked="true"/><label class="mr10">基本户</label>3.<input type="checkbox"/><label>一般户且用于:</label>
									<input type="checkbox"/><label class="mr10">结算</label><input type="checkbox"/><label class="mr10">贷款</label>或 <input type="checkbox"/><label>其它:</label>	<span class="line_input">    </span><br/>
								4.<input type="checkbox"/><label class="mr10">临时户</label>5.<input type="checkbox"/><label>专用户且账户资金性质为:</label><span class="line_input mr10"> </span>6.<input type="checkbox"/><label>NRA账户且国家代码为:</label><span class="line_input mr10"> </span>
							<#elseif data.remark28 == "03">
								1.<input type="checkbox"/><label class="mr10">定期账户</label>2.<input type="checkbox"/><label class="mr10">基本户</label>3.<input type="checkbox" checked="true"/><label>一般户且用于:</label>
									<#if data.remark29 == "01">
										<input type="checkbox" checked="true"/><label class="mr10">结算</label><input type="checkbox"/><label class="mr10">贷款</label>或 <input type="checkbox"/><label>其它:</label>	<span class="line_input">    </span><br/>
									<#elseif data.remark29 == "02">
										<input type="checkbox"/><label class="mr10">结算</label><input type="checkbox" checked="true"/><label class="mr10">贷款</label>或 <input type="checkbox"/><label>其它:</label>	<span class="line_input">    </span><br/>
									<#else>
										<input type="checkbox"/><label class="mr10">结算</label><input type="checkbox"/><label class="mr10">贷款</label>或 <input type="checkbox" checked="true"/><label>其它:</label>	<span class="line_input">${data.remark30}</span><br/>
									</#if>
								4.<input type="checkbox"/><label class="mr10">临时户</label>5.<input type="checkbox"/><label>专用户且账户资金性质为:</label><span class="line_input mr10"> </span>6.<input type="checkbox"/><label>NRA账户且国家代码为:</label><span class="line_input mr10"> </span>
							<#elseif data.remark28 == "04">
								1.<input type="checkbox"/><label class="mr10">定期账户</label>2.<input type="checkbox"/><label class="mr10">基本户</label>3.<input type="checkbox"/><label>一般户且用于:</label>
									<input type="checkbox"/><label class="mr10">结算</label><input type="checkbox"/><label class="mr10">贷款</label>或 <input type="checkbox"/><label>其它:</label>	<span class="line_input">    </span><br/>
								4.<input type="checkbox" checked="true"/><label class="mr10">临时户</label>5.<input type="checkbox"/><label>专用户且账户资金性质为:</label><span class="line_input mr10"> </span>6.<input type="checkbox"/><label>NRA账户且国家代码为:</label><span class="line_input mr10"> </span>
							<#elseif data.remark28 == "05">
								1.<input type="checkbox"/><label class="mr10">定期账户</label>2.<input type="checkbox"/><label class="mr10">基本户</label>3.<input type="checkbox"/><label>一般户且用于:</label>
									<input type="checkbox"/><label class="mr10">结算</label><input type="checkbox"/><label class="mr10">贷款</label>或 <input type="checkbox"/><label>其它:</label>	<span class="line_input">    </span><br/>
								4.<input type="checkbox"/><label class="mr10">临时户</label>5.<input type="checkbox"  checked="true"/><label>专用户且账户资金性质为:</label><span class="line_input mr10">${data.remark31}</span>6.<input type="checkbox"/><label>NRA账户且国家代码为:</label><span class="line_input mr10"> </span>
							<#else>
								1.<input type="checkbox"/><label class="mr10">定期账户</label>2.<input type="checkbox"/><label class="mr10">基本户</label>3.<input type="checkbox"/><label>一般户且用于:</label>
									<input type="checkbox"/><label class="mr10">结算</label><input type="checkbox"/><label class="mr10">贷款</label>或 <input type="checkbox"/><label>其它:</label>	<span class="line_input">    </span><br/>
								4.<input type="checkbox"/><label class="mr10">临时户</label>5.<input type="checkbox"/><label>专用户且账户资金性质为:</label><span class="line_input mr10"> </span>6.<input type="checkbox" checked="true"/><label>NRA账户且国家代码为:</label><span class="line_input mr10">${data.remark32}</span>
							</#if>
						  </td>
						</tr>
						<tr>
							<td align="center">外  币</td>
							<td>
							币种:
							<#if data.remark33 == "01">
								1.<input type="checkbox" checked="true"/><label class="mr10">美元</label>2.<input type="checkbox"/><label class="mr10">港币</label>3.<input type="checkbox"/><label class="mr10">欧元</label>4.<input type="checkbox"/><label class="mr10">日元</label>5.<input type="checkbox"/><label >其它:</label><span class="line_input">    </span><br/>
							<#elseif data.remark33 == "02">
								1.<input type="checkbox"/><label class="mr10">美元</label>2.<input type="checkbox" checked="true"/><label class="mr10">港币</label>3.<input type="checkbox"/><label class="mr10">欧元</label>4.<input type="checkbox"/><label class="mr10">日元</label>5.<input type="checkbox"/><label >其它:</label><span class="line_input">    </span><br/>
							<#elseif data.remark33 == "03">
								1.<input type="checkbox"/><label class="mr10">美元</label>2.<input type="checkbox"/><label class="mr10">港币</label>3.<input type="checkbox" checked="true"/><label class="mr10">欧元</label>4.<input type="checkbox"/><label class="mr10">日元</label>5.<input type="checkbox"/><label >其它:</label><span class="line_input">    </span><br/>
							<#elseif data.remark33 == "04">
								1.<input type="checkbox"/><label class="mr10">美元</label>2.<input type="checkbox"/><label class="mr10">港币</label>3.<input type="checkbox"/><label class="mr10">欧元</label>4.<input type="checkbox" checked="true"/><label class="mr10">日元</label>5.<input type="checkbox"/><label >其它:</label><span class="line_input">    </span><br/>
							<#else>
								1.<input type="checkbox"/><label class="mr10">美元</label>2.<input type="checkbox"/><label class="mr10">港币</label>3.<input type="checkbox"/><label class="mr10">欧元</label>4.<input type="checkbox"/><label class="mr10">日元</label>5.<input type="checkbox" checked="true"/><label >其它:</label><span class="line_input">${data.remark34}</span><br/>
							</#if>
							
							种类:
							<#if data.remark35 == "01">
								1.<input type="checkbox" checked="true"/><label class="mr10">经常项目外汇账户</label>2.<input type="checkbox"/><label class="mr10">外汇资本金账户</label>3.<input type="checkbox"/><label class="mr10">外债账户</label>4.<input type="checkbox"/><label >其它:</label><span class="line_input">    </span>
							<#elseif data.remark35 == "02">
								1.<input type="checkbox"/><label class="mr10">经常项目外汇账户</label>2.<input type="checkbox" checked="true"/><label class="mr10">外汇资本金账户</label>3.<input type="checkbox"/><label class="mr10">外债账户</label>4.<input type="checkbox"/><label >其它:</label><span class="line_input">    </span>
							<#elseif data.remark35 == "03">
								1.<input type="checkbox"/><label class="mr10">经常项目外汇账户</label>2.<input type="checkbox"/><label class="mr10">外汇资本金账户</label>3.<input type="checkbox" checked="true"/><label class="mr10">外债账户</label>4.<input type="checkbox"/><label >其它:</label><span class="line_input">    </span>
							<#else>
								1.<input type="checkbox"/><label class="mr10">经常项目外汇账户</label>2.<input type="checkbox"/><label class="mr10">外汇资本金账户</label>3.<input type="checkbox"/><label class="mr10">外债账户</label>4.<input type="checkbox" checked="true"/><label >其它:</label><span class="line_input">${data.remark36}</span>
							</#if>
							</td>
						</tr>
					</table>
					<table cellspacing="0" border="1" cellpadding="4">
						<tr>
							<td colspan="3" class="table_title">账 户 信 息 2</td>
						</tr>
						<tr>
							<td align="center">控股股东或<br/>实际控制人</td>
						  <td colspan="2">名称:<span class="line_input mr10">${data.remark37}</span>
						  证件种类:
						  <#if data.remark38 == "01">
						  	1.<input type="checkbox" checked="true"/><label class="mr10">身份证</label>2.<input type="checkbox"/><label class="mr10">护照</label>3.<input type="checkbox"/><label>其它:</label>	<span class="line_input">    </span><br/>
						  <#elseif data.remark38 == "02">
						  	1.<input type="checkbox"/><label class="mr10">身份证</label>2.<input type="checkbox" checked="true"/><label class="mr10">护照</label>3.<input type="checkbox"/><label>其它:</label>	<span class="line_input">    </span><br/>
						  <#else>	
						  	1.<input type="checkbox"/><label class="mr10">身份证</label>2.<input type="checkbox"/><label class="mr10">护照</label>3.<input type="checkbox" checked="true"/><label>其它:</label>	<span class="line_input">${data.remark39}</span><br/>
						  </#if>
						  证件号码:<span class="line_input mr10">${data.remark40}</span>
						  证件到期日:
						  <#if data.remark41 == "01">
						  	1.<input type="checkbox" checked="true"/><label class="mr10">长期有效</label>2.<input type="checkbox"/><label >到期日</label><span class="line_input">    </span>年<span class="line_input">    </span>月<span class="line_input">    </span>日</td>
						  <#else>
						  	1.<input type="checkbox"/><label class="mr10">长期有效</label>2.<input type="checkbox" checked="true"/><label >到期日</label><span class="line_input">${data.remark42}</span>年<span class="line_input">${data.remark43}</span>月<span class="line_input">${data.remark44}</span>日</td>
						  </#if>
						</tr>
						<tr class="strong_area">
							<td rowspan="2" align="center"><p style="color: red;text-align: center;">税收居民身份<br/>信息</p></td>
							<td><p style="color: red">机构类别:
							<#if data.remark45 == "01">
							1.<input type="checkbox" checked="true"/><label class="mr10">消极非金融机构</label>2.<input type="checkbox"/>其他非金融机构</p></td>
							<#else>
							1.<input type="checkbox"/><label class="mr10">消极非金融机构</label>2.<input type="checkbox" checked="true"/>其他非金融机构</p></td>
							</#if>
							<td><p style="color: red">税收居民身份:
							<#if data.remark46 == "01">
							1.<input type="checkbox" checked="true"/><label class="mr10">非居民或多重税收身份</label>2.<input type="checkbox"/>仅中国税收居民</p></td>
							<#else>
							1.<input type="checkbox"/><label class="mr10">非居民或多重税收身份</label>2.<input type="checkbox" checked="true"/>仅中国税收居民</p></td>
							</#if>
						</tr>
						<tr class="strong_area">
							<td colspan="2"><p style="color: red">注:属于"消极非金融机构"或"非居民或多重税收身份"的,需进一步提供税收居民声明文件及相关补充资料。</p></td>
						</tr>
						<tr>
							<td align="center">上级法人或主管单位</td>
							<td colspan="2">名称:<span class="line_input">${data.remark47}</span><br/>注:申请单位如有上级法人或主管单位,需提供其证照资料及法定代表人/单位负责人身份证件资料。</td>
						</tr>
						<tr class="strong_area">
							<td align="center">网上/手机银行/橙e网服务</td>
							<td colspan="2">
							<#if data.remark48 == "01">
								<input type="checkbox" checked="true"/><label class="mr10">开通或加挂网上/手机银行/橙e网,且网上银行服务权限:</label>
							<#else>
								<input type="checkbox"/><label class="mr10">开通或加挂网上/手机银行/橙e网,且网上银行服务权限:</label>
							</#if>
							<#if data.remark49 == "01">
								<input type="checkbox" checked="true"/><label class="mr10">转账与查询(企业管理员可在网银端自设录入及复核用户)</label>
							<#else>
								<input type="checkbox"/><label class="mr10">转账与查询(企业管理员可在网银端自设录入及复核用户)</label>
							</#if>
							或 
							<#if data.remark50 == "01">
								<input type="checkbox" checked="true"/><label class="mr10">仅查询;</label>
							<#else>
								<input type="checkbox"/><label class="mr10">仅查询;</label>
							</#if>
							<br/><label class="mr10">接收网上/手机银行激活码的移动电话:</label>
							<#if data.remark51 == "01">
								<input type="checkbox" checked="true"/><label class="mr10">同法定代表人(单位负责人)电话</label><input type="checkbox"/><label>同财务负责人电话</label>
							<#else>
								<input type="checkbox"/><label class="mr10">同法定代表人(单位负责人)电话</label><input type="checkbox" checked="true"/><label>同财务负责人电话</label>
							</#if>
							<br/><b>USBKEY购买数量:<span class="line_input">${data.remark52}</span>个</b>
							</td>
						</tr>
						<tr>
							<td align="center">其它增值服务<br/>(可多选)</td>
							<td colspan="2"><b class="mr10">1.默认开通电话银行</b>
							<#if data.remark53 == "01">
								2.<input type="checkbox" checked="true"/><label>开通金卫士服务且签约移动电话为:
								<#if data.remark54??>
									①</label><span class="line_input">${data.remark54}</span><br/>
									<#if data.remark55??>
										②<span class="line_input">${data.remark54}</span>
										<#if data.remark56??>
											③<span class="line_input">${data.remark56}</span>;    
										<#else>
											③<span class="line_input">    </span>;    
										</#if>
									<#else>
										②<span class="line_input">    </span>③<span class="line_input">    </span>;    
									</#if>
								<#else>
									①</label><span class="line_input">    </span><br/>②<span class="line_input">    </span>③<span class="line_input">    </span>;    
								</#if>
							<#else>
							</#if>
							缴费方式为:
							<#if data.remark57 == "01">
								<input type="checkbox" checked="true"/><label class="mr10">按月</label><input type="checkbox"/><label class="mr10">按条</label><input type="checkbox"/>按年<br/>
							<#elseif data.remark57 == "02">
								<input type="checkbox"/><label class="mr10">按月</label><input type="checkbox" checked="true"/><label class="mr10">按条</label><input type="checkbox"/>按年<br/>
							<#else>
								<input type="checkbox"/><label class="mr10">按月</label><input type="checkbox"/><label class="mr10">按条</label><input type="checkbox" checked="true"/>按年<br/>
							</#if>
							<#if data.remark58 == "01">
								3.<input type="checkbox" checked="true"/><label class="mr10">开通通兑</label>
							<#else>
								3.<input type="checkbox"/><label class="mr10">开通通兑</label>
							</#if>
							<#if data.remark59 == "01">
								4.<input type="checkbox" checked="true"/><label>开通支付密码</label>
								<#if data.remark60 == "01">
									(支付密码器:<input type="checkbox" checked="true"/><label class="mr10">新开</label><input type="checkbox"/><label class="mr10">自备)</label>
								<#else>
									(支付密码器:<input type="checkbox"/><label class="mr10">新开</label><input type="checkbox" checked="true"/><label class="mr10">自备)</label>
								</#if>
								
							<#else>
								4.<input type="checkbox"/><label>开通支付密码</label>(支付密码器:<input type="checkbox"/><label class="mr10">新开</label><input type="checkbox"/><label class="mr10">自备)</label>
							</#if>
							<#if data.remark61 == "01">
								5.<input type="checkbox" checked="true"/><label>电子商业汇票签约</label>
							<#else>
								5.<input type="checkbox"/><label>电子商业汇票签约</label>
							</#if>
							</td>
						</tr>					
					</table>	
					<br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>
					<table cellspacing="0" border="1" cellpadding="4">
						<col width="34%"/>
						<col width="33%"/>
						<col width="33%"/>
						<tr>
							<td colspan="3" class="table_title">意 见</td>
						</tr>
						<tr class="link">
							<td align="center"><a href="#">xxxx审核意见</a></td>
							<td align="center"><a href="#">xxxx承诺及签章</a></td>
							<td align="center"><a href="#">xxxx审核意见</a></td>
						</tr>
						<tr>
							<td valign="top" style="position: relative" class="strong_area">
								<p style="text-indent: 24px">本单位因结算需要,申请在贵行开立账户,保证开户资料的真实、完整、合规。本单位已阅读、理解《平安银行单位账户管理协议》条款(后附),并同意按协议约定使用账户和办理业务。</p>
								<p style="padding: 60px 0 80px">法定代表人<strong style="font-weight: normal">或其授权人</strong>签章:<span class="line_input">${data.remark62}</span></p>
								<div style="position: absolute;width: 100%;bottom: 4px;right: 4px">
									<p style="padding: 20px 0 20px 0;">申请单位(公章)</p>
									<p style="text-align: right;padding-bottom:15px;"><span class="line_input">${data.remark63}</span>年<span class="line_input">${data.remark64}</span>月<span class="line_input">${data.remark65}</span>日</p>
								</div>
							</td>
							<td valign="top" style="position: relative">
								<p style="margin: 20px 0;"> 经办:<span class="line_input">${data.remark66}</span></p>
								<p style="position: relative"> 主管:<span class="line_input">${data.remark67}</span></p>
								<div style="position: relative;width: 100%;bottom: 4px;right: 4px">
									<p style="padding: 115px 0 0 0;margin: 20px 0;">开户银行(签章)</p>
									<p style="text-align: right;padding-bottom:15px;"><span class="line_input">${data.remark68}</span>年<span class="line_input">${data.remark69}</span>月<span class="line_input">${data.remark70}</span>日</p>
								</div>
							</td>
							<td valign="top" style="position: relative">
								<p style="text-align: center">(非核准类账户除外)</p>
								<p style="margin: 20px 0;"> 经办人(签章):<span class="line_input">${data.remark71}</span></p>
								<div style="position: relative;width: 100%;bottom: 4px;right: 4px">
									<br/><br/>
									<p style="padding: 105px 0 0 0;">中国人民银行(签章)</p>
									<br/>
									<p style="text-align: right;padding-bottom:15px;"><span class="line_input">${data.remark72}</span>年<span class="line_input">${data.remark73}</span>月<span class="line_input">${data.remark74}</span>日</p>
								</div>
							</td>
						</tr>
					</table>
					<div class="sign_area" style="width: 100%;">
						<div style="width: 45%;text-align: right">
							<b>客户经理UM号:<span class="line_input">${data.remark75}</span></b>
						</div>
						<div style="text-align; right;margin-left: 60px">
							<b>客户经理姓名:<span class="line_input">${data.remark76}</span></b>
						</div>
						<p class="clear"></p>
					</div>			
				</div>
				<div class="side_tips">
					<p>第</p>
					<p>一</p>
					<p>联</p>
					<p>:</p>
					<p>开</p>
					<p>户</p>
					<p>银</p>
					<p>行</p>
					<p>留</p>
					<p>存</p>
					<p style="margin-top: 80px;">第</p>
					<p>二</p>
					<p>联</p>
					<p>:</p>
					<p>申</p>
					<p>请</p>
					<p>单</p>
					<p>位</p>
					<p>留</p>
					<p>存</p>
				</div>									
			</div>
			<!--文档end-->
</body>
</html>

第四步:测试

java 复制代码
package com.zy.test;
 
import java.util.HashMap;
import java.util.Map;
 
import org.junit.Test;
 
import com.zy.common.templatebo.PDFTemplateBo;
import com.zy.common.utils.PDFUtil;
 
public class TestPDFUtil {
	
	@Test
	public void testGeneratePDF(){
		String templateName = "template";//需要选用的模板名称
		String targetPathRoot = "D:/temp/";//生成pdf的目标位置
		Map<String, Object> map = generateUnitOpenAccountApplicationData();//构建模板所需数据
		
		try {
			String path = PDFUtil.getPath();
			//System.out.println(path); //项目根路径
			PDFUtil.generateToFile(path,"templates/" + templateName + ".ftl", path + "/images/", map, targetPathRoot + templateName + ".pdf");
			System.out.println("生成PDF成功!");
		} catch (Exception e) {
			e.printStackTrace();
			System.out.println("生成PDF失败!");
		}
	}
 
	public Map<String, Object> generateUnitOpenAccountApplicationData() {
		Map<String, Object>map = new HashMap<String, Object>();
		PDFTemplateBo bo = new PDFTemplateBo();
 
		bo.setRemark1("张三");//存款人名称
		bo.setRemark2("02");//办公地址:01同注册地址,02其它  当此项值为02时要设置remark3、remark4、remark5、remark6的值
		bo.setRemark3("xxx");//具体办公地址:省
		bo.setRemark4("xxx");//具体办公地址:市
		bo.setRemark5("xxx");//具体办公地址:区/县
		bo.setRemark6("xxx");//具体办公地址:
		bo.setRemark7("03");//邮寄地址:01同注册地址,02同办公地址,03其他  当此项值为03时要设置remark8、remark9、remark10、remark11的值
		bo.setRemark8("xxx");//具体邮寄地址:省
		bo.setRemark9("xxx");//具体邮寄地址:市
		bo.setRemark10("xxx");//具体邮寄地址:区/县
		bo.setRemark11("xxx");//具体邮寄地址:
		
		bo.setRemark12("01");//联系信息:01法定代表人,02单位负责人
		bo.setRemark13("027");//办公电话:区号
		bo.setRemark14("88936");//办公电话:直线
		bo.setRemark15("985635");//办公电话:分机
		bo.setRemark16("13295684565");//办公电话:移动电话
		
		bo.setRemark17("赖总");//财务负责人:姓名
		bo.setRemark18("010");//办公电话:区 号
		bo.setRemark19("88968");//办公电话:直线
		bo.setRemark20("9435649");//办公电话:分机
		bo.setRemark21("18868365686");//办公电话:移动电话
		bo.setRemark22("2322423@qq.com");//电子邮箱
		
		bo.setRemark23("罗总");//财务经办人员:姓名
		bo.setRemark24("020");//办公电话:区 号
		bo.setRemark25("89468");//办公电话:直线
		bo.setRemark26("9845146");//办公电话:分机
		bo.setRemark27("16686866868");//办公电话:移动电话
		
		bo.setRemark28("05");//账户种类:人民币:01定期账户,02基本户,03一般户,04临时户,05专用户,06NRA账户    当此项值为03时要设置remark29的值  当此项为05时要设置remark31的值   当此项值为06时要设置remark32的值
		//vo.setRemark29("03");//一般户且用于:01结算,02贷款,03其它  当此项值为03时要设置remark30的值
		//vo.setRemark30("预算");//具体的其他账户类型
		
		bo.setRemark31("国有");//remark28值为05时要设置此项   专用户且账户资金性质为
		//vo.setRemark32("64987");//remark28值为06时要设置此项   NRA账户且国家代码为
		
		bo.setRemark33("05");//账户种类:外  币:币种:01美元,02港币,03欧元,04日元,05其他  当此项的值为05时要设置remark32的值
		bo.setRemark34("英镑");//具体的币种
		bo.setRemark35("04");//账户种类:外  币:种类:01经常项目外汇账户,02外汇资本金账户,03外债账户,04其他  当此项值为04时要设置remark34的值
		bo.setRemark36("具体的账户种类");//具体的种类
		bo.setRemark37("老祝");//控股股东或实际控制人
		bo.setRemark38("03");// 证件种类:01身份证,02护照,03其他  当此项值为03时要设置remark37的值
		bo.setRemark39("好男人证");//具体的证件种类名称
		bo.setRemark40("86686688");//证件号码
		bo.setRemark41("02");//证件到期日类型:01长期有效,02具体到期日  当此项值为02时要设置remark40、remark41、remark42的值
		bo.setRemark42("2080");//证件到期日  年
		bo.setRemark43("08");  //证件到期日  月
		bo.setRemark44("18");  //证件到期日  日
		
		bo.setRemark45("02");//机构类别:01消极非金融机构,02其他非金融机构
		bo.setRemark46("01");//税收居民身份:01非居民或多重税收身份,02仅中国税收居民
		bo.setRemark47("xxx");//上级法人或主管单位名称
		bo.setRemark48("01");//是否勾选 开通或加挂网上/手机银行/橙e网,且网上银行服务权限:01勾选,02不勾选
		bo.setRemark49("02");//是否勾选 转账与查询(企业管理员可在网银端自设录入及复核用户):01勾选,02不勾选
		bo.setRemark50("01");//是否勾选 仅查询:01勾选,02不勾选
		bo.setRemark51("02");//接收网上/手机银行激活码的移动电话:01同法定代表人(单位负责人)电话,02同财务负责人电话
		bo.setRemark52("20");//USBKEY购买数量
		
		bo.setRemark53("01");//其它增值服务:开通金卫士服务且签约移动电话:01勾选,02不勾选   当此项值为01时要设置remark52的值
		bo.setRemark54("13398595998");//电话号码1
		//vo.setRemark55("");//电话号码2
		//vo.setRemark56("");//电话号码3
		bo.setRemark57("02");//缴费方式:01按月,02按条,03按年
		bo.setRemark58("01");//是否勾选 开通通兑:01勾选,02不勾选
		bo.setRemark59("01");//是否勾选  开通支付密码:01勾选,02不勾选  当此项的值为01时要设置remark58的值
		bo.setRemark60("01");//支付密码器类型:01新开,02自备
		bo.setRemark61("01");//是否勾选  电子商业汇票签约 :01勾选,02不勾选
		
		bo.setRemark62("法定代表人");//法定代表人或其授权人签章
		bo.setRemark63("2018");//签章日期  年
		bo.setRemark64("03");  //签章日期  月
		bo.setRemark65("10");  //签章日期  日
		
		bo.setRemark66("经办签的字");//经办签字
		bo.setRemark67("主管签的字");//主管签字
		bo.setRemark68("2018");//签字日期  年
		bo.setRemark69("03");  //签字日期  月
		bo.setRemark70("10");  //签字日期  日
		
		bo.setRemark71("经办人的签章");//经办人(签章)
		bo.setRemark72("2018");//签章日期  年
		bo.setRemark73("03");//签章日期  月
		bo.setRemark74("10");//签章日期  日
		bo.setRemark75("88888888");//客户经理UM号
		bo.setRemark76("老刘");//客户经理姓名
		
		map.put("data", bo);
		
		return map;
	}
}
相关推荐
Elastic 中国社区官方博客5 分钟前
我们如何通过 70 多个拉取请求,将 OpenTelemetry Java agent 迁移到 invokedynamic
java·大数据·开发语言·elasticsearch·搜索引擎·全文检索·es
tyn18817 分钟前
记录本地安装nacos服务的方法及异常
java·开发语言
步行cgn1 小时前
Spring MVC 视图机制的核心接口与类
java·开发语言·后端·spring·mvc
y1su1 小时前
Leetcode 字符串模板
java·数据结构·算法·leetcode·职场和发展·动态规划
我命由我123452 小时前
Python 开发 - Python 的 pathlib
java·开发语言·后端·python·学习·java-ee·学习方法
苜蓿muxu3 小时前
Java 字符串拼接:+、StringBuilder、StringBuffer的区别
java
摇滚侠3 小时前
《Java并发编程之美》第 4 章 Java 并发包中原子操作类原理剖析 阅读笔记 7
java·笔记·python
旋律4144 小时前
同义方法区别(增加类与删除类)
java·后端
学到老活到老4 小时前
方法执行完了,对象为什么还占着内存?
java·jvm