|
|
@@ -1,991 +0,0 @@
|
|
|
-package com.hr.service.impl;
|
|
|
-
|
|
|
-import com.hr.esign.ClientHelper;
|
|
|
-import com.hr.esign.HtmlToPDFUtil;
|
|
|
-import com.hr.esign.SignHelper;
|
|
|
-import com.hr.param.EsignParmDto;
|
|
|
-import com.hr.service.EsignService;
|
|
|
-import com.hr.vo.EsignReturnDto;
|
|
|
-import com.itextpdf.io.font.PdfEncodings;
|
|
|
-import com.itextpdf.io.image.ImageData;
|
|
|
-import com.itextpdf.io.image.ImageDataFactory;
|
|
|
-import com.itextpdf.kernel.colors.ColorConstants;
|
|
|
-import com.itextpdf.kernel.font.PdfFont;
|
|
|
-import com.itextpdf.kernel.font.PdfFontFactory;
|
|
|
-import com.itextpdf.kernel.geom.Rectangle;
|
|
|
-import com.itextpdf.kernel.pdf.PdfDocument;
|
|
|
-import com.itextpdf.kernel.pdf.PdfPage;
|
|
|
-import com.itextpdf.kernel.pdf.PdfReader;
|
|
|
-import com.itextpdf.kernel.pdf.PdfWriter;
|
|
|
-import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
|
|
|
-import com.itextpdf.kernel.pdf.canvas.PdfCanvasConstants;
|
|
|
-import com.itextpdf.kernel.pdf.canvas.parser.PdfCanvasProcessor;
|
|
|
-import com.itextpdf.kernel.pdf.canvas.parser.listener.IPdfTextLocation;
|
|
|
-import com.itextpdf.kernel.pdf.canvas.parser.listener.RegexBasedLocationExtractionStrategy;
|
|
|
-import com.itextpdf.layout.Document;
|
|
|
-import com.itextpdf.layout.element.Image;
|
|
|
-import com.timevale.esign.paas.tech.bean.bean.PosBean;
|
|
|
-import com.timevale.esign.paas.tech.bean.request.PlatformSignParam;
|
|
|
-import com.timevale.esign.paas.tech.bean.request.SignFilePdfParam;
|
|
|
-import com.timevale.esign.paas.tech.bean.result.FileDigestSignResult;
|
|
|
-import com.timevale.esign.paas.tech.client.ServiceClient;
|
|
|
-import com.timevale.esign.paas.tech.enums.SignType;
|
|
|
-import com.yy.basedevelop.common.util.OSSUtil;
|
|
|
-import esign.utils.exception.SuperException;
|
|
|
-import freemarker.ext.beans.BeansWrapper;
|
|
|
-import freemarker.template.Configuration;
|
|
|
-import freemarker.template.Template;
|
|
|
-import lombok.extern.slf4j.Slf4j;
|
|
|
-
|
|
|
-import org.slf4j.Logger;
|
|
|
-import org.slf4j.LoggerFactory;
|
|
|
-import org.springframework.beans.factory.annotation.Autowired;
|
|
|
-import org.springframework.core.io.ClassPathResource;
|
|
|
-import org.springframework.core.io.Resource;
|
|
|
-import org.springframework.stereotype.Service;
|
|
|
-import org.springframework.util.FileCopyUtils;
|
|
|
-import org.springframework.web.client.RestTemplate;
|
|
|
-import org.zefer.pd4ml.PD4Constants;
|
|
|
-import org.zefer.pd4ml.PD4ML;
|
|
|
-import javax.imageio.ImageIO;
|
|
|
-import java.awt.*;
|
|
|
-import java.awt.image.BufferedImage;
|
|
|
-import java.io.*;
|
|
|
-import java.security.InvalidParameterException;
|
|
|
-import java.text.MessageFormat;
|
|
|
-import java.text.SimpleDateFormat;
|
|
|
-import java.util.*;
|
|
|
-import java.util.List;
|
|
|
-import java.util.regex.Matcher;
|
|
|
-import java.util.regex.Pattern;
|
|
|
-
|
|
|
-@Service
|
|
|
-@Slf4j
|
|
|
-public class EsignServiceImpl implements EsignService {
|
|
|
- private int topValue = 10;
|
|
|
- private int leftValue = 20;
|
|
|
- private int rightValue = 10;
|
|
|
- private int bottomValue = 10;
|
|
|
- private int userSpaceWidth = 1024;
|
|
|
- @Autowired
|
|
|
- private RestTemplate restTemplate;
|
|
|
- @Autowired
|
|
|
- private OSSUtil oSSUtil;
|
|
|
- private Pattern pattern = Pattern.compile("^\\d+-\\d+$");
|
|
|
- private Pattern pattern2 = Pattern.compile("^(\\d+)-(\\d+)$");
|
|
|
- private static final Logger LOGGER = LoggerFactory.getLogger(EsignServiceImpl.class);
|
|
|
- private static SignHelper signHelper;
|
|
|
-
|
|
|
- private byte[] fontBytes=null;
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- public void initEsign(){
|
|
|
- try {
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- if (true) {
|
|
|
- //1、注册客户端,全局使用,只需注册一次
|
|
|
- ClientHelper.registClient();
|
|
|
- }
|
|
|
-
|
|
|
- //2、获取已初始化的客户端,以便后续正常调用SDK提供的各种服务,全局使用,只需获取一次
|
|
|
- ServiceClient serviceClient = ClientHelper.getServiceClient(ClientHelper.getProjectId());
|
|
|
-
|
|
|
- //3、实例化辅助类
|
|
|
- signHelper = new SignHelper(serviceClient);
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- } catch (Exception e) {
|
|
|
-// e.getE().printStackTrace();
|
|
|
- log.error("系统加载,初始化E签宝失败",e);
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
- /**
|
|
|
- * 电子签章
|
|
|
- * @param parm
|
|
|
- * @return
|
|
|
- */
|
|
|
- @Override
|
|
|
- public EsignReturnDto platformSignByPdfStream(EsignParmDto parm) {
|
|
|
- checkParm(parm);
|
|
|
- EsignReturnDto esignReturnDto = new EsignReturnDto();
|
|
|
- try {
|
|
|
- /**
|
|
|
- * 平台自身PDF文件流签署
|
|
|
- */
|
|
|
- //-------------------------------------------开始盖章,不调用e签宝---------------------------------------------
|
|
|
- // 签章位置信息
|
|
|
- //处理freemarker内容,并生成pdf,返回pdf字节流
|
|
|
- byte[] srcPdfBytes=doConversion(dealFreeMarkerContent(parm.getFreeMarkerContent(), parm.getParmData()));
|
|
|
- InputStream inputStream = new ByteArrayInputStream(srcPdfBytes);
|
|
|
- ByteArrayOutputStream out = new ByteArrayOutputStream();
|
|
|
- PdfDocument pd = new PdfDocument(new PdfReader(inputStream), new PdfWriter(out));
|
|
|
-// InputStream inputStream = new ByteArrayInputStream(dto.getSrcPdfBytes());
|
|
|
-// PdfDocument pd = new PdfDocument(new PdfReader(inputStream), new PdfWriter(out));
|
|
|
- Document document = new Document(pd);
|
|
|
-
|
|
|
- /***----------------------------------------------------------------------------------------*******/
|
|
|
- /***----------------------------------------------------------------------------------------*******/
|
|
|
- /***----------------------------------------------------------------------------------------*******/
|
|
|
- //如果没有章则不盖章
|
|
|
- if(parm.getSealData()!=null) {
|
|
|
- //在原图片上面增加日期
|
|
|
- parm.setSealData(addTimestampToBase64Image(parm.getSealData(), parm.getAddFontHeight(), parm.getCharSpacing(), parm.getAddFontSize(),parm.getCreateTime()));
|
|
|
-
|
|
|
- //将签章转换为 图片,以便获取宽高
|
|
|
- byte[] imageBytes = Base64.getDecoder().decode(parm.getSealData());
|
|
|
- ByteArrayInputStream bis = new ByteArrayInputStream(imageBytes);
|
|
|
- BufferedImage originalImage = ImageIO.read(bis);
|
|
|
- bis.close();
|
|
|
- //得到图片的宽高
|
|
|
- int _width = originalImage.getWidth();
|
|
|
- int _height = originalImage.getHeight();
|
|
|
-
|
|
|
-
|
|
|
- if (originalImage == null) {
|
|
|
- throw new IllegalArgumentException("无效的图片数据");
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- int pageCount = pd.getNumberOfPages();
|
|
|
- Boolean limitpagenum = false;
|
|
|
- int[] limmitpagenums = null;
|
|
|
- if (parm.getPosPage() != null && !"".equals(parm.getPosPage())) {
|
|
|
- limitpagenum = isValidFormat(parm.getPosPage());
|
|
|
- limmitpagenums = extractNumbers(parm.getPosPage());
|
|
|
- }
|
|
|
- //遍历每一页
|
|
|
- for (int i = 1; i <= pageCount; i++) {
|
|
|
-
|
|
|
- if (limitpagenum == true && limmitpagenums != null && limmitpagenums.length == 2) {
|
|
|
- if (i < limmitpagenums[0] || i > limmitpagenums[1]) {
|
|
|
- continue;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- PdfPage page = pd.getPage(i);
|
|
|
- //查找页中的匹配文字,并定位到位置。
|
|
|
- RegexBasedLocationExtractionStrategy strategy = new RegexBasedLocationExtractionStrategy(parm.getKeyWord());
|
|
|
- PdfCanvasProcessor processor = new PdfCanvasProcessor(strategy);
|
|
|
- processor.processPageContent(page);
|
|
|
- Collection<IPdfTextLocation> resultantLocations = strategy.getResultantLocations();
|
|
|
-
|
|
|
- //自定义结果处理
|
|
|
- if (!resultantLocations.isEmpty()) {
|
|
|
- for (IPdfTextLocation item : resultantLocations) {
|
|
|
- Rectangle boundRectangle = item.getRectangle();
|
|
|
-// System.out.println(item.getText());
|
|
|
- ImageData imageData = ImageDataFactory.create(Base64.getDecoder().decode(parm.getSealData()));
|
|
|
-// System.out.println("关键字“" + dto.getKeyWord() + "” 的坐标为 x: " + boundRectangle.getX() + " ,y: " + boundRectangle.getY());
|
|
|
- Image image = new Image(imageData).scaleAbsolute(parm.getWidth(), parm.getWidth() * _height / _width).setFixedPosition(i,
|
|
|
- boundRectangle.getRight() + parm.getPosX(),
|
|
|
- boundRectangle.getBottom() - parm.getPosY());
|
|
|
- document.add(image);
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- document.close();
|
|
|
- pd.close();
|
|
|
- //输出文件
|
|
|
- out.close();
|
|
|
- byte[] filebytes=out.toByteArray();
|
|
|
-
|
|
|
-// File file222 = new File("D:\\_____Work\\output.pdf");
|
|
|
-//
|
|
|
-// try (FileOutputStream fos = new FileOutputStream(file222)) {
|
|
|
-// fos.write(filebytes);
|
|
|
-// fos.flush();
|
|
|
-// } catch (IOException e) {
|
|
|
-// e.printStackTrace();
|
|
|
-// }
|
|
|
-
|
|
|
-
|
|
|
- // 签署文件信息
|
|
|
- SignFilePdfParam file = new SignFilePdfParam();
|
|
|
- //PDF文件信息
|
|
|
-// String srcPdfPath = PATH_PREFEX + "test.pdf";
|
|
|
- //获取PDF文件的字节流
|
|
|
-// byte[] srcPdfBytes = parm.getSrcPdfBytes();
|
|
|
-
|
|
|
- file.setStreamFile(filebytes);// 待填充PDF文件本地二进制数据
|
|
|
- String filename="我的平台自身签署文件.pdf";
|
|
|
- if(parm.getFileName()!=null){
|
|
|
- filename=parm.getFileName();
|
|
|
- }
|
|
|
- file.setFileName(filename);
|
|
|
- //file.setDstPdfFile(PATH_PREFEX + "Signed_Platform.pdf");// 签署后PDF文件本地路径,含文件名(为空时返回签署后的文件流)
|
|
|
- //传入平台自身签署参数内
|
|
|
- PlatformSignParam platformSignParam = new PlatformSignParam();
|
|
|
- FileDigestSignResult signRst=null;
|
|
|
- //如果当前有用户签名信息,则还需要签用户
|
|
|
- if(parm.getSealDataUserName()!=null ){
|
|
|
-
|
|
|
- //获取了第一次盖章的pdf二进制
|
|
|
- file.setStreamFile(filebytes);
|
|
|
- platformSignParam.setFileBean(file);//签署文件信息
|
|
|
- int addtimestampfontsize=10;
|
|
|
- int addfontheight=13;
|
|
|
- if(parm.getSealDataUserName().length()<4){
|
|
|
- addtimestampfontsize=11;
|
|
|
- addfontheight=13;
|
|
|
- }
|
|
|
- if(parm.getSealDataUserName().length()>8){
|
|
|
- parm.setPosXUser(parm.getPosXUser()+10+1*parm.getSealDataUserName().length());
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- //根据用户名字生成红色透明背景图片
|
|
|
- platformSignParam.setSealData(addTimestampToBase64Image(generateTransparentImageWithText(parm.getSealDataUserName()),addfontheight,0,addtimestampfontsize,parm.getCreateTime()));
|
|
|
- platformSignParam.setSignType(SignType.Key);
|
|
|
- List<PosBean> posBeansUser = new ArrayList<>();
|
|
|
- platformSignParam.setPosBeans(posBeansUser);
|
|
|
- PosBean signPos1 = new PosBean();
|
|
|
- String posPage1="1";
|
|
|
- if(parm.getPosPage()!=null){
|
|
|
- posPage1=parm.getPosPage();
|
|
|
- }
|
|
|
- signPos1.setPosPage(posPage1);// 签署页码(除关键字签章外,页码均不可为空)若为多页签章,支持指定多个页码,例如格式:“1-3,5,8“
|
|
|
- int posX1=50;
|
|
|
- if(parm.getPosXUser()!=null){
|
|
|
- posX1=parm.getPosXUser();
|
|
|
- }
|
|
|
- signPos1.setPosX(posX1);// 签署位置X坐标,若为关键字定位,相对于关键字的X坐标偏移量,默认0
|
|
|
- int posY1=0;
|
|
|
- if(parm.getPosYUser()!=null){
|
|
|
- posY1=parm.getPosYUser();
|
|
|
- }
|
|
|
- signPos1.setPosY(posY1);// 签署位置Y坐标,若为关键字定位,相对于关键字的Y坐标偏移量,默认0
|
|
|
- String KeyWord1="";
|
|
|
- if(parm.getKeyWordUser()!=null){
|
|
|
- KeyWord1=parm.getKeyWordUser();
|
|
|
- }
|
|
|
- signPos1.setKeyWord(KeyWord1);// 关键字,仅限关键字签章时有效,若为关键字定位时,不可空
|
|
|
- int with1=130;
|
|
|
- // 创建一个宽度为100像素,高度为50像素的透明背景图片
|
|
|
-// int width = 130;
|
|
|
- if(parm.getSealDataUserName().length()*11>with1){
|
|
|
- with1 = parm.getSealDataUserName().length()*11;
|
|
|
- }
|
|
|
-// if(parm.getSealDataUserName().length()*11>parm.getWidthUser()){
|
|
|
-// parm.setWidthUser(parm.getSealDataUserName().length()*11);
|
|
|
-// }
|
|
|
-// if(parm.getWidthUser()!=null){
|
|
|
-// with1=parm.getWidthUser();
|
|
|
-// }
|
|
|
- signPos1.setWidth(with1+20);// 印章展现宽度,将以此宽度对印章图片做同比缩放。
|
|
|
-// signPos1.setAddSignTime(true);// 是否显示本地签署时间,需要width设置92以上才可以看到时间
|
|
|
- posBeansUser.add(signPos1);
|
|
|
- platformSignParam.setPosBeans(posBeansUser);//签章位置信息
|
|
|
- signRst=signHelper.platformSign(platformSignParam);
|
|
|
- if (signRst.getErrCode() != 0) {
|
|
|
- String typeMsg="Esign平台自身";
|
|
|
- throw new SuperException(
|
|
|
- MessageFormat.format("{0}用户签章,签署失败: errCode = {1},msg = {2}",
|
|
|
- typeMsg, signRst.getErrCode(), signRst.getMsg()));
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-// if(1==1){
|
|
|
-////// 定义一个文件名字进行接收获取文件
|
|
|
-// FileOutputStream fileOut = new FileOutputStream(new File("D:\\_____Work\\aaa.pdf" ));
|
|
|
-// byte[] buf = new byte[1024 * 8];
|
|
|
-// InputStream ipt = new ByteArrayInputStream(signRst.getStream());
|
|
|
-// while (true) {
|
|
|
-// int read = 0;
|
|
|
-// if (ipt != null) {
|
|
|
-// read = ipt.read(buf);
|
|
|
-// }
|
|
|
-// if (read == -1) {
|
|
|
-// break;
|
|
|
-// }
|
|
|
-// fileOut.write(buf, 0, read);
|
|
|
-// }
|
|
|
-// return new EsignReturnDto();
|
|
|
-// }
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- if (signRst.getStream() != null) {
|
|
|
-
|
|
|
- String url=null;
|
|
|
- if(parm.getOssFileName()!=null ) {
|
|
|
- InputStream ipt = new ByteArrayInputStream(signRst.getStream());
|
|
|
- if (parm.getOssFileName().startsWith("/")) {
|
|
|
- url = oSSUtil.upLoadInputStream(ipt, "esgin" + parm.getOssFileName());
|
|
|
- } else {
|
|
|
- url = oSSUtil.upLoadInputStream(ipt, "esgin/" + parm.getOssFileName());
|
|
|
- }
|
|
|
- log.info("E签宝签章后PDF,OSS文件地址. URL: {}" , url);
|
|
|
- esignReturnDto.setOssurl(url);
|
|
|
- }
|
|
|
- }
|
|
|
- }else {
|
|
|
- throw new RuntimeException("esign未传入用户名字");
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- }
|
|
|
- catch (Exception eex){
|
|
|
- esignReturnDto.setMsg(eex.getMessage());
|
|
|
- log.error("Esign平台自身签署程序异常",eex);
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- return esignReturnDto;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- public EsignReturnDto hrSignByPdfStream(EsignParmDto dto) {
|
|
|
- checkParm(dto);
|
|
|
- EsignReturnDto esignReturnDto = new EsignReturnDto();
|
|
|
- try {
|
|
|
- //读取二进制成为pdf文件
|
|
|
-// InputStream inputStream = new ByteArrayInputStream(dto.getSrcPdfBytes());
|
|
|
- //处理freemarker内容,并生成pdf,返回pdf字节流
|
|
|
- InputStream inputStream = new ByteArrayInputStream(doConversion(dealFreeMarkerContent(dto.getFreeMarkerContent(), dto.getParmData())));
|
|
|
- ByteArrayOutputStream out = new ByteArrayOutputStream();
|
|
|
- PdfDocument pd = new PdfDocument(new PdfReader(inputStream), new PdfWriter(out));
|
|
|
-// InputStream inputStream = new ByteArrayInputStream(dto.getSrcPdfBytes());
|
|
|
-// PdfDocument pd = new PdfDocument(new PdfReader(inputStream), new PdfWriter(out));
|
|
|
- Document document = new Document(pd);
|
|
|
-
|
|
|
- int _width=100;
|
|
|
- int _height=100;
|
|
|
-
|
|
|
-
|
|
|
- //在原图片上面增加日期
|
|
|
- if(dto.getSealData()!=null) {
|
|
|
- dto.setSealData(addTimestampToBase64Image(dto.getSealData(), dto.getAddFontHeight(), dto.getCharSpacing(), dto.getAddFontSize(),dto.getCreateTime()));
|
|
|
-
|
|
|
-
|
|
|
- //将签章转换为 图片,以便获取宽高
|
|
|
- byte[] imageBytes = Base64.getDecoder().decode(dto.getSealData());
|
|
|
- ByteArrayInputStream bis = new ByteArrayInputStream(imageBytes);
|
|
|
- BufferedImage originalImage = ImageIO.read(bis);
|
|
|
- bis.close();
|
|
|
- //得到图片的宽高
|
|
|
- _width = originalImage.getWidth();
|
|
|
- _height = originalImage.getHeight();
|
|
|
-
|
|
|
-
|
|
|
- if (originalImage == null) {
|
|
|
- throw new IllegalArgumentException("无效的图片数据");
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- int pageCount = pd.getNumberOfPages();
|
|
|
- Boolean limitpagenum=false;
|
|
|
- int[] limmitpagenums=null;
|
|
|
- if(dto.getPosPage()!=null && !"".equals(dto.getPosPage())) {
|
|
|
- limitpagenum=isValidFormat(dto.getPosPage());
|
|
|
- limmitpagenums=extractNumbers(dto.getPosPage());
|
|
|
- }
|
|
|
- //遍历每一页
|
|
|
- for (int i = 1; i <= pageCount; i++) {
|
|
|
-
|
|
|
- if(limitpagenum==true && limmitpagenums!=null && limmitpagenums.length==2){
|
|
|
- if(i<limmitpagenums[0] || i>limmitpagenums[1]){
|
|
|
- continue;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- PdfPage page = pd.getPage(i);
|
|
|
-
|
|
|
- if(dto.getKeyWord() !=null && !"".equals(dto.getKeyWord()) && dto.getSealData()!=null) {
|
|
|
- //查找页中的匹配文字,并定位到位置。
|
|
|
- RegexBasedLocationExtractionStrategy strategy = new RegexBasedLocationExtractionStrategy(dto.getKeyWord());
|
|
|
- PdfCanvasProcessor processor = new PdfCanvasProcessor(strategy);
|
|
|
- processor.processPageContent(page);
|
|
|
- Collection<IPdfTextLocation> resultantLocations = strategy.getResultantLocations();
|
|
|
-
|
|
|
- //自定义结果处理
|
|
|
- if (!resultantLocations.isEmpty()) {
|
|
|
- for (IPdfTextLocation item : resultantLocations) {
|
|
|
- Rectangle boundRectangle = item.getRectangle();
|
|
|
-// System.out.println(item.getText());
|
|
|
- ImageData imageData = ImageDataFactory.create(Base64.getDecoder().decode(dto.getSealData()));
|
|
|
-// System.out.println("关键字“" + dto.getKeyWord() + "” 的坐标为 x: " + boundRectangle.getX() + " ,y: " + boundRectangle.getY());
|
|
|
- Image image = new Image(imageData).scaleAbsolute(dto.getWidth(), dto.getWidth() * _height / _width).setFixedPosition(i, boundRectangle.getRight() + dto.getPosX(), boundRectangle.getBottom() - dto.getPosY());
|
|
|
- document.add(image);
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- //如果需要签章用户名字
|
|
|
- if(dto.getSealDataUserName()!=null && dto.getKeyWordUser()!= null){
|
|
|
- //查找页中的匹配文字,并定位到位置。
|
|
|
- RegexBasedLocationExtractionStrategy strategy2 = new RegexBasedLocationExtractionStrategy(dto.getKeyWordUser());
|
|
|
- PdfCanvasProcessor processor2 = new PdfCanvasProcessor(strategy2);
|
|
|
- processor2.processPageContent(page);
|
|
|
- Collection<IPdfTextLocation> resultantLocations2 = strategy2.getResultantLocations();
|
|
|
-
|
|
|
- //自定义结果处理
|
|
|
- if (!resultantLocations2.isEmpty()) {
|
|
|
- for (IPdfTextLocation item : resultantLocations2) {
|
|
|
- Rectangle boundRectangle2 = item.getRectangle();
|
|
|
-// System.out.println(item.getText());
|
|
|
- int addtimestampfontsize=10;
|
|
|
- int addfontheight=11;
|
|
|
- if(dto.getSealDataUserName().length()<=4){
|
|
|
- addtimestampfontsize=11;
|
|
|
- addfontheight=13;
|
|
|
- }
|
|
|
- String textimgbase64=addTimestampToBase64Image(generateTransparentImageWithText(dto.getSealDataUserName()),addfontheight,0,addtimestampfontsize,dto.getCreateTime());
|
|
|
- ImageData imageData = ImageDataFactory.create(Base64.getDecoder().decode(textimgbase64));
|
|
|
-
|
|
|
- //将签章转换为 图片,以便获取宽高
|
|
|
- byte[] imageBytes2 = Base64.getDecoder().decode(textimgbase64);
|
|
|
- ByteArrayInputStream bis2 = new ByteArrayInputStream(imageBytes2);
|
|
|
- BufferedImage originalImage2 = ImageIO.read(bis2);
|
|
|
- bis2.close();
|
|
|
- //得到图片的宽高
|
|
|
- int _width2=originalImage2.getWidth();
|
|
|
- int _height2=originalImage2.getHeight();
|
|
|
-
|
|
|
- dto.setWidthUser(93);
|
|
|
- if(dto.getSealDataUserName().length()*11>dto.getWidthUser()){
|
|
|
- dto.setWidthUser(dto.getSealDataUserName().length()*11);
|
|
|
- }
|
|
|
-// System.out.println("关键字“" + dto.getKeyWord() + "” 的坐标为 x: " + boundRectangle.getX() + " ,y: " + boundRectangle.getY());
|
|
|
- Image image = new Image(imageData).scaleAbsolute(dto.getWidthUser(), dto.getWidthUser()*_height2/_width2).setFixedPosition(i, boundRectangle2.getRight() + dto.getPosXUser(), boundRectangle2.getBottom()-dto.getPosYUser());
|
|
|
- document.add(image);
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- document.close();
|
|
|
- pd.close();
|
|
|
- //输出文件
|
|
|
- out.close();
|
|
|
- byte[] filebytes=out.toByteArray();
|
|
|
- InputStream ipt = new ByteArrayInputStream(filebytes);
|
|
|
-
|
|
|
-// if(1==1){
|
|
|
-//// 定义一个文件名字进行接收获取文件
|
|
|
-// FileOutputStream fileOut = new FileOutputStream(new File("D:\\_____Work\\aaa_hr.pdf" ));
|
|
|
-// byte[] buf = new byte[1024 * 8];
|
|
|
-// while (true) {
|
|
|
-// int read = 0;
|
|
|
-// if (ipt != null) {
|
|
|
-// read = ipt.read(buf);
|
|
|
-// }
|
|
|
-// if (read == -1) {
|
|
|
-// break;
|
|
|
-// }
|
|
|
-// fileOut.write(buf, 0, read);
|
|
|
-// }
|
|
|
-// return new EsignReturnDto();
|
|
|
-// }
|
|
|
-
|
|
|
-
|
|
|
- String url=null;
|
|
|
- if(dto.getOssFileName()!=null ) {
|
|
|
- if (dto.getOssFileName().startsWith("/")) {
|
|
|
- url = oSSUtil.upLoadInputStream(ipt, "esgin_hr" + dto.getOssFileName());
|
|
|
- } else {
|
|
|
- url = oSSUtil.upLoadInputStream(ipt, "esgin_hr/" + dto.getOssFileName());
|
|
|
- }
|
|
|
- log.info("惠融生成签章文件PDF地址URL:{} " , url);
|
|
|
- esignReturnDto.setOssurl(url);
|
|
|
- }
|
|
|
-
|
|
|
-// oSSUtil.upLoadStream();
|
|
|
-
|
|
|
-
|
|
|
- }catch (Exception e){
|
|
|
- esignReturnDto.setMsg(e.getMessage());
|
|
|
- log.error("生成签章pdf文件处理异常",e);
|
|
|
- }
|
|
|
-
|
|
|
- return esignReturnDto;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- /***
|
|
|
- * 匹配数字"2-15" 的格式
|
|
|
- * @param input
|
|
|
- * @return
|
|
|
- */
|
|
|
- public int[] extractNumbers(String input) {
|
|
|
- if (input == null || input.isEmpty()) {
|
|
|
- return new int[0]; // 返回空数组表示无效输入
|
|
|
- }
|
|
|
-
|
|
|
- // 正则表达式:匹配类似 "2-15" 的格式
|
|
|
- Matcher matcher = pattern2.matcher(input);
|
|
|
-
|
|
|
- if (matcher.matches()) {
|
|
|
- int start = Integer.parseInt(matcher.group(1));
|
|
|
- int end = Integer.parseInt(matcher.group(2));
|
|
|
- return new int[]{start, end};
|
|
|
- } else {
|
|
|
- return new int[0]; // 不匹配格式,返回空数组
|
|
|
- }
|
|
|
- }
|
|
|
- public Boolean isValidFormat(String input) {
|
|
|
- if (input == null || input.isEmpty()) {
|
|
|
- return false;
|
|
|
- }
|
|
|
- // 正则表达式:匹配类似 "2-11" 的格式,只允许正整数
|
|
|
- Matcher matcher = pattern.matcher(input);
|
|
|
- return matcher.matches();
|
|
|
- }
|
|
|
-
|
|
|
- public String addTimestampToBase64Image(String base64Image,int addfontheight, int charSpacing,int fontSize,Date siggnTime) {
|
|
|
- try {
|
|
|
- // 1. 解码 Base64 为图片
|
|
|
- byte[] imageBytes = Base64.getDecoder().decode(base64Image);
|
|
|
- ByteArrayInputStream bis = new ByteArrayInputStream(imageBytes);
|
|
|
- BufferedImage originalImage = ImageIO.read(bis);
|
|
|
- bis.close();
|
|
|
-
|
|
|
- if (originalImage == null) {
|
|
|
- throw new IllegalArgumentException("无效的图片数据");
|
|
|
- }
|
|
|
-
|
|
|
- // 2. 创建新图片,在下方留出空间添加文字
|
|
|
- int width = originalImage.getWidth();
|
|
|
- int height = originalImage.getHeight() + addfontheight; // 预留文字区域
|
|
|
-
|
|
|
- BufferedImage newImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
|
|
|
- Graphics2D g2d = newImage.createGraphics();
|
|
|
-
|
|
|
- // 抗锯齿设置
|
|
|
- g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
|
|
- g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
|
|
|
-
|
|
|
- // 绘制原图
|
|
|
- g2d.drawImage(originalImage, 0, 0, null);
|
|
|
-
|
|
|
- // 时间戳
|
|
|
- String timestamp = new SimpleDateFormat("yyyy-MM-dd").format(siggnTime);
|
|
|
- String year=timestamp.substring(0,4);
|
|
|
- String month=timestamp.substring(5,7);
|
|
|
- String day=timestamp.substring(8,10);
|
|
|
- timestamp=year+"年"+month+"月"+day+"日";
|
|
|
-
|
|
|
- Font font = null;
|
|
|
- try {
|
|
|
- // 获取 InputStream
|
|
|
- File fontFile = new File("/fonts/simsun.ttf");
|
|
|
- if(fontFile.exists()){
|
|
|
- font = Font.createFont(Font.TRUETYPE_FONT, fontFile);
|
|
|
- }else {
|
|
|
- InputStream inputStream = getFontInput();
|
|
|
- font = Font.createFont(Font.TRUETYPE_FONT, inputStream);
|
|
|
- }
|
|
|
- } catch (FontFormatException e) {
|
|
|
- log.error("字体加载失败");
|
|
|
- } catch (IOException e) {
|
|
|
- log.error("文件不存在");
|
|
|
- }
|
|
|
- // 修复NullPointerException:如果字体加载失败,使用默认字体
|
|
|
- if (font == null) {
|
|
|
- log.warn("无法加载自定义字体,使用系统默认字体");
|
|
|
- font = new Font("SansSerif", Font.PLAIN, 11);
|
|
|
- } else {
|
|
|
-
|
|
|
- // 设置字体大小,比如 24
|
|
|
- font = font.deriveFont(13f);
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
-// Font font = new Font("Default", Font.CENTER_BASELINE, 15); // 使用宋体,粗体,大小为24
|
|
|
- g2d.setFont(font);
|
|
|
-
|
|
|
- // 设置颜色,透明度为70%
|
|
|
- Color color = new Color(255, 0, 0, 179); // 红色,透明度为70%
|
|
|
- g2d.setColor(color);
|
|
|
- g2d.setColor(Color.red);
|
|
|
-
|
|
|
- // 设置起始位置
|
|
|
- int textY = height - 5; // 距离底部10像素
|
|
|
- int currentX = 10; // 初始 X 坐标(可改为居中)
|
|
|
-
|
|
|
- // 居中计算(总宽度)
|
|
|
- FontMetrics fm = g2d.getFontMetrics();
|
|
|
- int totalWidth = 0;
|
|
|
- for (int i = 0; i < timestamp.length(); i++) {
|
|
|
- totalWidth += fm.charWidth(timestamp.charAt(i));
|
|
|
- }
|
|
|
- totalWidth += charSpacing * (timestamp.length() - 1); // 加上字符间距
|
|
|
- currentX = (width - totalWidth) / 2;
|
|
|
-
|
|
|
- // 逐个字符绘制,添加字符间距
|
|
|
- for (int i = 0; i < timestamp.length(); i++) {
|
|
|
- char c = timestamp.charAt(i);
|
|
|
- int charWidth = fm.charWidth(c);
|
|
|
- g2d.drawString(String.valueOf(c), currentX, textY);
|
|
|
- currentX += charWidth + charSpacing; // 增加字符宽度 + 间距
|
|
|
- }
|
|
|
-
|
|
|
- g2d.dispose();
|
|
|
-
|
|
|
- // 3. 将新图片转为 Base64 返回
|
|
|
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
|
|
- ImageIO.write(newImage, "PNG", bos);
|
|
|
- byte[] newImageBytes = bos.toByteArray();
|
|
|
- return Base64.getEncoder().encodeToString(newImageBytes);
|
|
|
-
|
|
|
- } catch (Exception e) {
|
|
|
- log.error("添加时间戳处理异常",e);
|
|
|
- return null;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- /**
|
|
|
- * 在指定位置添加文字
|
|
|
- *
|
|
|
- * @param pdfDoc PdfDocument对象
|
|
|
- * @param page 页码(从1开始)
|
|
|
- * @param posX X坐标
|
|
|
- * @param posY Y坐标
|
|
|
- * @param text 要添加的文字
|
|
|
- * @param fontSize 字体大小
|
|
|
- */
|
|
|
- public static void addText(PdfDocument pdfDoc, int page, int posX, int posY, String text, int fontSize,String keyWord) throws IOException {
|
|
|
-// PdfCanvas canvas = new PdfCanvas(pdfDoc.getPage(page));
|
|
|
- //查找页中的匹配文字,并定位到位置。
|
|
|
- RegexBasedLocationExtractionStrategy strategy = new RegexBasedLocationExtractionStrategy(keyWord);
|
|
|
- PdfCanvasProcessor processor = new PdfCanvasProcessor(strategy);
|
|
|
- PdfPage pdfpage = pdfDoc.getPage(page);
|
|
|
- processor.processPageContent(pdfpage);
|
|
|
- Collection<IPdfTextLocation> resultantLocations = strategy.getResultantLocations();
|
|
|
-
|
|
|
- float findPosX=-1;
|
|
|
- float findPosY=-1;
|
|
|
- //自定义结果处理
|
|
|
- if (!resultantLocations.isEmpty()) {
|
|
|
- for (IPdfTextLocation item : resultantLocations) {
|
|
|
- Rectangle boundRectangle = item.getRectangle();
|
|
|
- findPosX=boundRectangle.getRight();
|
|
|
- findPosY=boundRectangle.getBottom() ;
|
|
|
- System.out.println(findPosX+"---"+findPosY);
|
|
|
- }
|
|
|
- }
|
|
|
- // 加载字体
|
|
|
-// com.itextpdf.kernel.font.PdfFont font = com.itextpdf.kernel.font.PdfFontFactory.createFont();
|
|
|
-// PdfFont font = PdfFontFactory.createFont("STSong-Light", "UniGB-UCS2-H");
|
|
|
-
|
|
|
- if(findPosX>-1 && findPosY>-1) {
|
|
|
-// // 设置字体和字体大小
|
|
|
-// canvas.beginText()
|
|
|
-// .setFontAndSize(font, fontSize)
|
|
|
-// .moveText(findPosX + posX, findPosY + posY)
|
|
|
-// .showText(text)
|
|
|
-// .endText();
|
|
|
-// PdfCanvas canvas = new PdfCanvas(pdfDoc.getPage(page));
|
|
|
-
|
|
|
- // 在指定位置插入文字
|
|
|
-// Text textElement = new Text(text)
|
|
|
-// .setFontColor(com.itextpdf.kernel.colors.ColorConstants.BLACK)
|
|
|
-// .setFontSize(12);
|
|
|
-// Paragraph paragraph = new Paragraph(textElement);
|
|
|
-// canvas.beginText().setColor(com.itextpdf.kernel.colors.ColorConstants.BLACK,true)
|
|
|
-// .setFontAndSize(font, fontSize)
|
|
|
-// .moveText(findPosX + posX, findPosY + posY)
|
|
|
-// .showText(text)
|
|
|
-// .endText();
|
|
|
- try (InputStream fontStream = EsignServiceImpl.class.getClassLoader().getResourceAsStream("otherIf-config/siyuan.ttf")) {
|
|
|
- if (fontStream == null) {
|
|
|
- throw new IOException("Font file not found: otherIf-config/siyuan.ttf");
|
|
|
- }
|
|
|
-
|
|
|
- // 加载字体文件
|
|
|
- PdfFont font = PdfFontFactory.createFont(inputStreamToByteArray(fontStream), PdfEncodings.IDENTITY_H);
|
|
|
- // 通过PDF页来构建画布
|
|
|
- PdfCanvas pdfCanvas = new PdfCanvas(pdfDoc.getPage(page));
|
|
|
-
|
|
|
- pdfCanvas.beginText() // 开启文本
|
|
|
- .moveText(findPosX+posX, findPosY+posY) // 设置文本在画布的指定位置
|
|
|
- .setFontAndSize(font, fontSize) // 设置文本的样式和大小
|
|
|
- // 设置文本的呈现方式,这里我设置的是既有描边也有填充
|
|
|
- .setTextRenderingMode(PdfCanvasConstants.TextRenderingMode.FILL_CLIP)
|
|
|
- .setStrokeColor(ColorConstants.BLACK) // 描边绿色
|
|
|
-// .setFillColor(ColorConstants.BLACK) // 填充红色
|
|
|
- .showText(text)
|
|
|
- .endText(); // 关闭文本
|
|
|
- // 释放画布。使用完画布后,请使用此方法。
|
|
|
- pdfCanvas.release();
|
|
|
-
|
|
|
- } catch (Exception e) {
|
|
|
- e.printStackTrace();
|
|
|
- } finally {
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- public static byte[] inputStreamToByteArray(InputStream inputStream) throws IOException {
|
|
|
- try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
|
|
|
- byte[] buffer = new byte[1024];
|
|
|
- int bytesRead;
|
|
|
- while ((bytesRead = inputStream.read(buffer)) != -1) {
|
|
|
- byteArrayOutputStream.write(buffer, 0, bytesRead);
|
|
|
- }
|
|
|
- return byteArrayOutputStream.toByteArray();
|
|
|
- } finally {
|
|
|
- if (inputStream != null) {
|
|
|
- inputStream.close();
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- public String convertVue(String vueHtml) {
|
|
|
- // 1. 转换插值表达式 {{ expression }} -> ${expression}
|
|
|
- vueHtml = vueHtml.replaceAll("\\{\\{\\s*(.*?)\\s*}}", "\\${$1}");
|
|
|
-
|
|
|
- // 2. 转换 v-if 指令
|
|
|
- Pattern vIfPattern = Pattern.compile("<(\\w+)\\s+v-if=\"([^\"]+)\"([^>]*)>");
|
|
|
- Matcher vIfMatcher = vIfPattern.matcher(vueHtml);
|
|
|
- StringBuffer result = new StringBuffer();
|
|
|
- while (vIfMatcher.find()) {
|
|
|
- String tag = vIfMatcher.group(1); // 标签名
|
|
|
- String condition = vIfMatcher.group(2); // 条件表达式
|
|
|
- String attributes = vIfMatcher.group(3); // 其他属性
|
|
|
- // 替换为 FreeMarker 的 <#if> 标签
|
|
|
- vIfMatcher.appendReplacement(result, "<#if " + condition + "><" + tag + attributes + ">");
|
|
|
- }
|
|
|
- vIfMatcher.appendTail(result);
|
|
|
- vueHtml = result.toString();
|
|
|
-
|
|
|
- // 3. 转换 v-for 指令
|
|
|
- Pattern vForPattern = Pattern.compile("<(\\w+)\\s+v-for=\"(\\w+)\\s+in\\s+([^\"]+)\"([^>]*)>");
|
|
|
- Matcher vForMatcher = vForPattern.matcher(vueHtml);
|
|
|
- result = new StringBuffer();
|
|
|
- while (vForMatcher.find()) {
|
|
|
- String tag = vForMatcher.group(1); // 标签名
|
|
|
- String item = vForMatcher.group(2); // 循环变量
|
|
|
- String collection = vForMatcher.group(3); // 集合
|
|
|
- String attributes = vForMatcher.group(4); // 其他属性
|
|
|
- // 替换为 FreeMarker 的 <#list> 标签
|
|
|
- vForMatcher.appendReplacement(result, "<#list " + collection + " as " + item + "><" + tag + attributes + ">");
|
|
|
- }
|
|
|
- vForMatcher.appendTail(result);
|
|
|
- vueHtml = result.toString();
|
|
|
-
|
|
|
- // 4. 添加结束标签 </#if> 和 </#list>
|
|
|
- vueHtml = vueHtml.replaceAll("</(\\w+)>", "</$1></#if></#list>");
|
|
|
-
|
|
|
- return vueHtml;
|
|
|
- }
|
|
|
-
|
|
|
- public String generateTransparentImageWithText(String userName) {
|
|
|
- // 创建一个宽度为100像素,高度为50像素的透明背景图片
|
|
|
- int width = 130;
|
|
|
- if(userName.length()*13>width){
|
|
|
- width = userName.length()*13;
|
|
|
- }
|
|
|
- int height = 30;
|
|
|
- BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
|
|
|
-
|
|
|
- // 获取Graphics2D对象以绘制图像
|
|
|
- Graphics2D g2d = image.createGraphics();
|
|
|
-
|
|
|
- // 创建 ClassPathResource 对象
|
|
|
-// Resource resource = new ClassPathResource("fonts/simsun.ttf");
|
|
|
-
|
|
|
-//
|
|
|
-// String classPath = HtmlToPDFUtil.class.getResource("/").getPath() + "fonts"+"/simsun.ttf";
|
|
|
-// System.out.println(classPath);
|
|
|
- // 设置字体
|
|
|
- Font font = null;
|
|
|
- try {
|
|
|
- // 获取 InputStream
|
|
|
- File fontFile = new File("/fonts/simsun.ttf");
|
|
|
- if(fontFile.exists()) {
|
|
|
- font = Font.createFont(Font.TRUETYPE_FONT, fontFile);
|
|
|
- }else {
|
|
|
- InputStream inputStream = getFontInput();
|
|
|
-// Resource resource = new ClassPathResource("fonts/simsun.ttf");
|
|
|
- font = Font.createFont(Font.TRUETYPE_FONT, inputStream);
|
|
|
- }
|
|
|
- } catch (FontFormatException e) {
|
|
|
- log.error("字体加载失败");
|
|
|
- } catch (IOException e) {
|
|
|
- log.error("文件不存在");
|
|
|
- }
|
|
|
-
|
|
|
- // 修复NullPointerException:如果字体加载失败,使用默认字体
|
|
|
- if (font == null) {
|
|
|
- log.warn("无法加载自定义字体,使用系统默认字体");
|
|
|
- font = new Font("SansSerif", Font.PLAIN, 11);
|
|
|
- } else {
|
|
|
- if(userName.length()<=4){
|
|
|
- font = font.deriveFont(15f);
|
|
|
- }else {
|
|
|
- // 设置字体大小,比如 24
|
|
|
- font = font.deriveFont(13f);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-// Font font = new Font("Default", Font.CENTER_BASELINE, 15); // 使用宋体,粗体,大小为24
|
|
|
- g2d.setFont(font);
|
|
|
-
|
|
|
- // 设置颜色,透明度为70%
|
|
|
- Color color = new Color(255, 0, 0, 179); // 红色,透明度为70%
|
|
|
- g2d.setColor(color);
|
|
|
-
|
|
|
- // 计算文本的位置
|
|
|
- String text = userName;
|
|
|
- int x = (width - g2d.getFontMetrics().stringWidth(text)) / 2; // 水平居中
|
|
|
- int y = (height + g2d.getFontMetrics().getAscent()) / 2; // 垂直居中
|
|
|
-
|
|
|
- // 绘制文本
|
|
|
- g2d.drawString(text, x, y);
|
|
|
-
|
|
|
- // 释放资源
|
|
|
- g2d.dispose();
|
|
|
-
|
|
|
- // 将BufferedImage转换为字节数组
|
|
|
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
|
|
- try {
|
|
|
- ImageIO.write(image, "png", baos);
|
|
|
- } catch (IOException e) {
|
|
|
- log.error("Esign将图片文件转化为字节数组字符串,并对其进行Base64编码处理异常,异常信息:{}", e.getMessage(), e);
|
|
|
- return null;
|
|
|
- }
|
|
|
-
|
|
|
- // 将字节数组转换为Base64字符串
|
|
|
- byte[] imageBytes = baos.toByteArray();
|
|
|
- String base64Image = Base64.getEncoder().encodeToString(imageBytes);
|
|
|
-
|
|
|
- return base64Image;
|
|
|
- }
|
|
|
-
|
|
|
- public byte[] doConversion(String htmlDocument) throws InvalidParameterException, IOException {
|
|
|
- PD4ML pd4ml = new PD4ML();
|
|
|
- pd4ml.enableDebugInfo();
|
|
|
- pd4ml.setHtmlWidth(userSpaceWidth);
|
|
|
- pd4ml.setPageSize(pd4ml.changePageOrientation(PD4Constants.A4));
|
|
|
- pd4ml.setPageInsetsMM(new Insets(topValue, leftValue, bottomValue, rightValue));
|
|
|
- pd4ml.addStyle("BODY {margin: 0; font-family:MSJH;}", true);//background:#111;
|
|
|
- pd4ml.addStyle(".table {display: flex;flex-direction: column;width: 100%;height: auto;gap: 0;border: 1px solid #333;}",true);
|
|
|
- pd4ml.addStyle(".table .table-label {width: 100%;font-weight: 600;display: grid;grid-template-columns: 30px 40px 40px 1fr 1fr 30px;}",true);
|
|
|
- pd4ml.addStyle(".table .table-row {width: 100%;display: grid;grid-template-columns: 30px 40px 40px 1fr 1fr 30px;}",true);
|
|
|
- pd4ml.addStyle(".table .table-row div {display: flex;justify-content: center;align-items: center;box-sizing: border-box;border: 1px solid #333;height: auto;line-height: 1.5;word-break: break-all;}",true);
|
|
|
- pd4ml.addStyle("/* 表格整体样式 */\n" +
|
|
|
- " table {\n" +
|
|
|
- " width: 100%; /* 表格宽度占满父容器 */\n" +
|
|
|
- " border-collapse: collapse; /* 合并边框 */\n" +
|
|
|
- " text-align: center; /* 文字居中对齐 */\n" +
|
|
|
- " }\n" +
|
|
|
- "\n" +
|
|
|
- " /* 表头样式 */\n" +
|
|
|
- " th {\n" +
|
|
|
- " text-align:center; "+
|
|
|
- " font-weight: bold; /* 加粗 */\n" +
|
|
|
- " border: 1px solid #333; /* 边框 */\n" +
|
|
|
- " }\n" +
|
|
|
- "\n" +
|
|
|
- " /* 表格单元格样式 */\n" +
|
|
|
- " td {\n" +
|
|
|
- " text-align: center; vertical-align: middle;"+
|
|
|
- " border: 1px solid #333; /* 边框 */\n" +
|
|
|
- " }\n" +
|
|
|
-// "\n" +
|
|
|
-// " /* 表格行样式 */\n" +
|
|
|
-// " tr:nth-child(even) {\n" +
|
|
|
-// " background-color: #f9f9f9; /* 偶数行背景颜色(浅灰色) */\n" +
|
|
|
-// " }\n" +
|
|
|
-// "\n" +
|
|
|
- " /* 表格标题样式 */\n" +
|
|
|
- " caption {\n" +
|
|
|
- " font-weight: bold; /* 加粗 */\n" +
|
|
|
- " }",true);
|
|
|
- String classPath = HtmlToPDFUtil.class.getResource("/") + "fonts";
|
|
|
- pd4ml.useTTF(classPath, true);
|
|
|
- pd4ml.setDefaultTTFs("SimSun", "SimSun", "SimSun");
|
|
|
- ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
|
|
- pd4ml.render(new StringReader(htmlDocument), byteArrayOutputStream);
|
|
|
- byteArrayOutputStream.close();
|
|
|
- return byteArrayOutputStream.toByteArray();
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 处理FreeMarker模板
|
|
|
- * @param html
|
|
|
- * @param map
|
|
|
- * @return
|
|
|
- */
|
|
|
- private String dealFreeMarkerContent(String html, Map<String, Object> map) {
|
|
|
- // 边界检查
|
|
|
- if (html == null || html.isEmpty() || map == null || map.isEmpty()) {
|
|
|
- return html; // 如果模板或参数为空,直接返回原始模板
|
|
|
- }
|
|
|
- if(map==null){
|
|
|
- map=new HashMap<>();
|
|
|
- }
|
|
|
-
|
|
|
- try {
|
|
|
- // 创建 FreeMarker 配置对象
|
|
|
- Configuration cfg = new Configuration();
|
|
|
- cfg.setClassicCompatible(true);
|
|
|
- cfg.setLogTemplateExceptions(false);
|
|
|
- cfg.setWrapUncheckedExceptions(true);
|
|
|
- BeansWrapper wp= new BeansWrapper();
|
|
|
- cfg.setObjectWrapper(wp);
|
|
|
-
|
|
|
- // 将 HTML 内容包装为 FreeMarker 模板
|
|
|
- Template template = new Template("templateName", new StringReader(html), cfg);
|
|
|
-
|
|
|
- // 创建 StringWriter 用于捕获输出
|
|
|
- StringWriter writer = new StringWriter();
|
|
|
-
|
|
|
- // 使用 FreeMarker 处理模板并生成结果
|
|
|
- template.process(map, writer);
|
|
|
-
|
|
|
- // 返回渲染后的字符串
|
|
|
- return writer.toString();
|
|
|
- } catch (Exception e) {
|
|
|
- // 捕获异常并返回原始 HTML 或错误信息
|
|
|
- log.error("EsignService Error processing template", e);
|
|
|
- return html; // 或者返回错误信息,例如 "Error processing template"
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- private void checkParm(EsignParmDto parm){
|
|
|
- if(parm==null){
|
|
|
- throw new IllegalArgumentException("参数不能为空");
|
|
|
- }
|
|
|
- if(parm.getKeyWordUser()==null){
|
|
|
- throw new IllegalArgumentException("KeyWordUser不能为空");
|
|
|
- }
|
|
|
- if(parm.getFreeMarkerContent()==null){
|
|
|
- throw new IllegalArgumentException("freeMarkerContent不能为空");
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- public ByteArrayInputStream getFontInput() throws IOException {
|
|
|
- if(fontBytes==null) {
|
|
|
- Resource resource = new ClassPathResource("fonts/simsun.ttf");
|
|
|
- ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
|
|
- FileCopyUtils.copy(resource.getInputStream(), outputStream);
|
|
|
- fontBytes = outputStream.toByteArray();
|
|
|
- }
|
|
|
- return new ByteArrayInputStream( fontBytes);
|
|
|
- }
|
|
|
-
|
|
|
-}
|