需要生成的证书是这样的:
1.需要用到的maven包
<!--证书生成开始--><!-- .itextpdf/itextpdf --><dependency><groupId>com.itextpdf</groupId><artifactId>itextpdf</artifactId><version>5.5.11</version></dependency><!-- .l/xmlworker --><dependency><groupId>l</groupId><artifactId>xmlworker</artifactId><version>5.5.11</version></dependency><!-- .freemarker/freemarker --><dependency><groupId>org.freemarker</groupId><artifactId>freemarker</artifactId><version>2.3.19</version></dependency><!-- .xhtmlrenderer/flying-saucer-pdf --><dependency><groupId>org.xhtmlrenderer</groupId><artifactId>flying-saucer-pdf</artifactId><version>9.1.5</version></dependency><!-- .xhtmlrenderer/flying-saucer-pdf-itext5 --><dependency><groupId>org.xhtmlrenderer</groupId><artifactId>flying-saucer-pdf-itext5</artifactId><version>9.1.5</version></dependency><!-- .apache.velocity/velocity --><dependency><groupId>org.apache.velocity</groupId><artifactId>velocity</artifactId><version>1.7</version></dependency><!--证书生成结束-->
l中写入静态文件路径
静态文件是放在 下列路径中
由于我的需要生成的PDF文件中的字体用到了楷体、黑体等字体,所以需要将这些文件引入到程序中
<build><resources><resource><directory>src/main/resources</directory><includes><include>**/*.xml</include><include>**/*.html</include><include>**/*.ttf</include><include>**/*.TTF</include><include>**/*.ttc</include></includes><!--是否替换资源中的属性--><filtering>false</filtering></resource></resources></build>
3.生成文件工具类
本地测试时,我文件放的位置是在D:/netplan/upload/目录下
测试环境和生产环境下,我文件放的位置是/opt/upload/下
你的html文件必须要放在你指定的路径 D:/netplan/upload/templateHtml/下
import pdf.BaseFont;
import DocumentException;
plate.Configuration;
plate.Template;
plate.TemplateException;
import gcnvd.framework.util.UUIDUtil;
slf4j.Slf4j;
import org.apachemons.lang.CharEncoding;
import org.xhtmlrenderer.layout.SharedContext;
import org.xhtmlrenderer.pdf.ITextFontResolver;
import org.xhtmlrenderer.pdf.ITextRenderer;import java.io.*;
import java.nio.charset.StandardCharsets;
import java.time.LocalDate;
import java.util.HashMap;
import java.util.Map;/*** Html生成PDF文件*/
@Slf4j
public class HtmlToPDFUtils {/*** 模板存放位置 /opt/upload/templateHtml/*/private static final String TEMPLATE_HTML_PATH = "D:/netplan/upload/templateHtml/";/*** 技术支撑单位 certificate.html*/private static final String HTML_NAME = "compatibilityCertificate.html";/*** 临时HTML文件存放位置 /opt/upload/tempHtml/yyyy-MM-dd/时间戳.html*/private static final String TEMP_HTML_PATH = "D:/netplan/upload/templateHtml/";/*** 黑体*/private static final String SIMHEI = "f";/*** 楷体*/private static final String SIMKAI = "f";/*** 隶书*/private static final String SIMLI = "fonts/SIMLI.TTF";/*** 宋体*/private static final String SIMSUN = "";/*** 渲染HTML文件并生成PDF文件** @param params 传递到模板的参数* @param targetFile 目标文件的地址*/public static void createPdfFile(Map<String, Object> params, String targetFile) {Template template = null;String renderResult = "";//创建fm的配置Configuration config = new Configuration();//指定默认编码格式config.setDefaultEncoding(CharEncoding.UTF_8);try {config.setDirectoryForTemplateLoading(new File(TEMPLATE_HTML_PATH));template = Template(HTML_NAME, CharEncoding.UTF_8);} catch (IOException e) {e.printStackTrace();}String outTempHtmlFilePath = TEMP_HTML_PATH + w().toString() + "/" + System.currentTimeMillis() + ".html";File writeFile = new File(outTempHtmlFilePath);File fileParent = ParentFile();if (!ists()) {fileParent.mkdirs();}try {ateNewFile();Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(writeFile), CharEncoding.UTF_8));template.process(params, writer);FileInputStream inputStream = new FileInputStream(outTempHtmlFilePath);int length = inputStream.available();byte bytes[] = new byte[length];ad(bytes);inputStream.close();renderResult = new String(bytes, StandardCharsets.UTF_8);} catch (IOException e) {e.printStackTrace();} catch (TemplateException e) {e.printStackTrace();}try {createPdf(renderResult, targetFile);} catch (IOException e) {e.printStackTrace();} catch (DocumentException e) {e.printStackTrace();}}public static void createPdf(String content, String dest) throws IOException, DocumentException {log.info("-----------------------content-----------------------");log.info(content);log.info("-----------------------content-----------------------");ITextRenderer renderer = new ITextRenderer();SharedContext sharedContext = SharedContext();// 解决base64图片支持问题sharedContext.setReplacedElementFactory(new Base64ImgReplacedElementFactory());TextRenderer().setSmoothingThreshold(0);ITextFontResolver fontResolver = FontResolver();fontResolver.addFont(SIMHEI, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);fontResolver.addFont(SIMLI, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);fontResolver.addFont(SIMKAI, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);fontResolver.addFont(SIMSUN, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);// 解析html生成pdfrenderer.setDocumentFromString(content);//解决图片相对路径的问题renderer.layout();atePDF(new FileOutputStream(dest));}public static void main(String[] args) {String outFilePath = "D:/netplan/" + Uuid() + ".pdf";Map<String, Object> data = new HashMap();data.put("certificateCode", "CNNVD-XX-XXXXXX");data.put("companyName", "北京XXXXXX有限公司");data.put("registerAddress", "北京市海淀区XXXXXXXXXXX");data.put("creditCode", "XXXXXXXXXXXXXXXX");data.put("productName", "测试产品名称");data.put("productVersion", "V1.03");data.put("productModel", "SKPI2000XXX");data.put("reviewTime", "2021年06月25日");data.put("expiryTime", "2022年06月25日");data.put("currentTime", "2021年08月06日");createPdfFile(data, outFilePath);}}
图片工具类
import BadElementException;
import Image;
import dec.Base64;
import org.w3c.dom.Element;
import d.FSImage;
import d.ReplacedElement;
import d.ReplacedElementFactory;
import d.UserAgentCallback;
import org.xhtmlrenderer.layout.LayoutContext;
import org.xhtmlrenderer.pdf.ITextFSImage;
import org.xhtmlrenderer.pdf.ITextImageElement;
import der.BlockBox;
import org.d.FormSubmissionListener;import java.io.IOException;/*** * 图片base64支持,把图片转换为itext自己的图片对象* * @author Administrator* ** */
public class Base64ImgReplacedElementFactory implements ReplacedElementFactory {/*** 实现createReplacedElement 替换html中的Img标签** @param c 上下文* @param box 盒子* @param uac 回调* @param cssWidth css宽* @param cssHeight css高* @return ReplacedElement*/@Overridepublic ReplacedElement createReplacedElement(LayoutContext c, BlockBox box, UserAgentCallback uac,int cssWidth, int cssHeight) {Element e = Element();if (e == null) {return null;}String nodeName = e.getNodeName();// 找到img标签if (nodeName.equals("img")) {String attribute = e.getAttribute("src");FSImage fsImage;try {// 生成itext图像fsImage = buildImage(attribute, uac);} catch (BadElementException e1) {fsImage = null;} catch (IOException e1) {fsImage = null;}if (fsImage != null) {// 对图像进行缩放if (cssWidth != -1 || cssHeight != -1) {fsImage.scale(cssWidth, cssHeight);}return new ITextImageElement(fsImage);}}return null;}/*** 将base64编码解码并生成itext图像** @param srcAttr 属性* @param uac 回调* @return FSImage* @throws IOException io异常* @throws BadElementException BadElementException*/protected FSImage buildImage(String srcAttr, UserAgentCallback uac) throws IOException,BadElementException {FSImage fsImage;if (srcAttr.startsWith("data:image/")) {String b64encoded = srcAttr.substring(srcAttr.indexOf("base64,") + "base64,".length(),srcAttr.length());// 解码byte[] decodedBytes = Base64.decode(b64encoded);fsImage = new Instance(decodedBytes));} else {fsImage = ImageResource(srcAttr).getImage();}return fsImage;}/*** 实现remove** @param e 元素*/@Overridepublic void remove(Element e) {}/*** 实现reset*/@Overridepublic void reset() {}/*** 实现setFormSubmissionListener** @param formsubmissionlistener 监听*/@Overridepublic void setFormSubmissionListener(FormSubmissionListener formsubmissionlistener) {}
}
4.html证书模板
其中图片需要使用到的是绝对路径
当前图片展示的是本地的路径 在服务器上运行的话需换成服务器上的路径
还有需要注意生成文件的大小 在HTML文件的@page
中,当前我的纸张大小为A4纸
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><title>兼容性服务证书</title><style>@page {size: a4}* {margin: 0;padding: 0;list-style: none;}.main {background-color: #fffbc6;width: 700px;height: 1000px;position: relative;}.main .mainin {margin: auto;background-color: #fffbc6;background: url("file:///D:/netplan/images/border.png") no-repeat;background-size: 640px 940px;width: 640px;height: 940px;text-align: center;font-family: 'NSimSun';position: relative;top: 30px;}.main .mainin img {margin: 70px 0 40px 0;}.main .mainin .p1 {font: normal small-caps normal 38px/45px 'LiSu';}.main .mainin .p2 {font: normal small-caps normal 50px/55px 'LiSu';}.main .mainin .certificate-code {letter-spacing: 5px;font: normal small-caps normal 18px/80px 'SimHei';}.main .mainin pany-name {letter-spacing: 5px;font: normal small-caps normal 28px/40px 'SimHei';}.main .mainin pany-info {margin-top: 10px;letter-spacing: 2px;font-size: 18px;}.main .mainin pany-info span::after {content: '';display: inline-block;width: 100%;}.main .mainin pany-info span {font: normal small-caps normal 16px/40px 'SimHei';}.main .mainin .peoduct-info {letter-spacing: 5px;margin-top: 40px;font: normal small-caps normal 28px/40px 'SimHei';}.main .mainin .peoduct-version {letter-spacing: 5px;font: normal small-caps normal 28px/40px 'SimHei';}.main .mainin .instruction {font: normal small-caps normal 20px/55px 'SimHei';}.main .mainin .date-info {font-family: 'NSimSun';margin-top: 40px;}.main .mainin .date-info {font: normal small-caps normal 18px/35px 'SimHei';}.main .mainin .date-info span {letter-spacing: 10px;}.main .mainin .approve-info {margin-top: 40px;}.main .mainin .approve-info div {text-align: right;margin-right: 100px;font: normal small-caps normal 18px/35px 'SimHei';}</style></head><body><div class="main"><div class="mainin"><img src="file:///D:/netplan/images/certificateLogo.png" width="150" height="150" /><p class="p1">国家信息安全漏洞库</p><p class="p2">兼容性资质证书</p><p class="certificate-code"><span>证书号:</span>${certificateCode}</p><p class="company-name">${companyName}</p><div class="company-info">(${registerAddress}<br />统一社会信用代码:${creditCode})</div><p class="peoduct-info">${productName}</p><p class="peoduct-version">(${productVersion}/ ${productModel})</p><p class="instruction">此证书仅适用于该产品/系统的上述版本和型号</p><div class="date-info"><span>签发日期</span>:${reviewTime}<br /><span>有效期至</span>:${expiryTime}</div><div class="approve-info"><div>${currentTime}</div></div></div></div></body>
</html>
本文发布于:2024-01-28 23:29:45,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170645578811077.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |