package com.nq.service.impl; import com.nq.common.ServerResponse; import com.nq.pojo.User; import com.nq.service.IUserAgreementService; import com.nq.utils.PropertiesUtil; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.*; import java.text.SimpleDateFormat; import java.util.Date; import com.itextpdf.text.*; import com.itextpdf.text.pdf.*; import com.itextpdf.text.pdf.BaseFont; import com.itextpdf.text.pdf.parser.PdfTextExtractor; import com.itextpdf.text.pdf.parser.SimpleTextExtractionStrategy; @Service("iUserAgreementService") public class UserAgreementServiceImpl implements IUserAgreementService { private static final Logger log = LoggerFactory.getLogger(UserAgreementServiceImpl.class); @Autowired private com.nq.service.IUserService iUserService; @Override public ServerResponse generateAgreementPdf(HttpServletRequest request) { try { User user = iUserService.getCurrentUser(request); if (user == null) { return ServerResponse.createByErrorMsg("用户未登录"); } if (StringUtils.isBlank(user.getRealName()) || StringUtils.isBlank(user.getIdCard()) || StringUtils.isBlank(user.getRegAddress())) { return ServerResponse.createByErrorMsg("用户信息不完整,请先完成实名认证"); } // 检查是否已生成PDF String pdfDir = PropertiesUtil.getProperty("agreement.pdf.dir", System.getProperty("user.dir") + "/agreement_pdf"); File dir = new File(pdfDir); if (!dir.exists()) { dir.mkdirs(); } String pdfFileName = "agreement_" + user.getId() + ".pdf"; File pdfFile = new File(dir, pdfFileName); if (pdfFile.exists()) { return ServerResponse.createBySuccess(pdfFileName); } // 获取模板文件路径 String templatePath = this.getClass().getResource("/templates").getPath(); if (templatePath.startsWith("/") && System.getProperty("os.name").toLowerCase().contains("windows")) { templatePath = templatePath.substring(1); } templatePath = templatePath.replaceAll("%20", " "); if (templatePath.contains("file:")) { templatePath = templatePath.substring(templatePath.indexOf("file:") + 5); } if (templatePath.contains("!")) { templatePath = templatePath.substring(0, templatePath.indexOf("!")); } // 使用PDF模板文件 File pdfTemplate = new File(templatePath, "中原证券股票分成协议(电子正式版).pdf"); if (!pdfTemplate.exists()) { return ServerResponse.createByErrorMsg("PDF模板文件不存在"); } // 从PDF模板生成新的PDF,替换占位符 generatePdfFromTemplate(pdfTemplate, pdfFile, user); return ServerResponse.createBySuccess(pdfFileName); } catch (Exception e) { log.error("生成用户协议PDF失败", e); return ServerResponse.createByErrorMsg("生成PDF失败:" + e.getMessage()); } } public static void main(String[] args) { generateAgreementPdf11(); } public static void generateAgreementPdf11() { try { // 检查是否已生成PDF String pdfDir = PropertiesUtil.getProperty("agreement.pdf.dir", System.getProperty("user.dir") + "/agreement_pdf"); File dir = new File(pdfDir); if (!dir.exists()) { dir.mkdirs(); } String pdfFileName = "agreement_111.pdf"; File pdfFile = new File(dir, pdfFileName); // 获取模板文件路径 String templatePath = "D:/work/A-stock/src/main/resources/templates"; if (templatePath.startsWith("/") && System.getProperty("os.name").toLowerCase().contains("windows")) { templatePath = templatePath.substring(1); } templatePath = templatePath.replaceAll("%20", " "); if (templatePath.contains("file:")) { templatePath = templatePath.substring(templatePath.indexOf("file:") + 5); } if (templatePath.contains("!")) { templatePath = templatePath.substring(0, templatePath.indexOf("!")); } // 使用PDF模板文件 File pdfTemplate = new File(templatePath, "中原证券股票分成协议(电子正式版).pdf"); if (!pdfTemplate.exists()) { System.out.println("PDF模板文件不存在"); } // 从PDF模板生成新的PDF,替换占位符 generatePdfFromTemplate1(pdfTemplate, pdfFile); } catch (Exception e) { log.error("生成用户协议PDF失败", e); } } public static void generatePdfFromTemplate1(File templatePdf, File outputPdf) throws Exception { PdfReader reader = new PdfReader(new FileInputStream(templatePdf)); PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(outputPdf)); // 设置中文字体 BaseFont baseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED); Font font = new Font(baseFont, 12, Font.NORMAL); // Font boldFont = new Font(baseFont, 12, Font.BOLD); // BaseFont baseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED); // Font font = new Font(baseFont, 5, Font.BOLD); SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日"); String currentDate = sdf.format(new Date()); // 准备替换的数据 String realName = "陈大雷"; String idCard = "433123198802456635"; String address = "广东省清远市三八街道明星之城18栋2单元1506"; // 获取PDF页数 int pageCount = reader.getNumberOfPages(); // 在每一页上查找并替换占位符 for (int pageNum = 1; pageNum <= pageCount; pageNum++) { PdfContentByte canvas = stamper.getOverContent(pageNum); Rectangle pageSize = reader.getPageSize(pageNum); // 提取PDF文本查找占位符位置 String pageText = PdfTextExtractor.getTextFromPage(reader, pageNum, new SimpleTextExtractionStrategy()); // 在PDF上查找并替换占位符 replacePlaceholdersInPdf1(canvas, pageSize, pageText, realName, idCard, address, currentDate, font,pageNum); // 添加签名 if(pageNum == 3){ // 添加签名 addHeaderImageToPdf(canvas, templatePdf.getParent(), pageSize); } } stamper.close(); reader.close(); } /** * 在PDF上替换占位符(使用文本覆盖方式) */ public static void replacePlaceholdersInPdf1(PdfContentByte canvas, Rectangle pageSize, String pageText, String realName, String idCard, String address, String currentDate, Font font,int pageNum) throws Exception { // 查找占位符在文本中的位置,然后估算在PDF中的坐标 // 由于PDF坐标系统复杂,这里使用固定位置替换 // 实际使用时需要根据PDF模板的具体布局调整坐标 float margin = 50; float lineHeight = 14; float startY = pageSize.getHeight() - 194; if(pageNum == 1){ replacePlaceholder1(canvas, "", realName, margin + 75, startY, 0, font); startY -= lineHeight; replacePlaceholder1(canvas, "", address, margin + 75, startY-2, 0, font); startY -= lineHeight; replacePlaceholder1(canvas, "", idCard, margin + 95, startY-2, 0, font); } if(pageNum == 3){ replacePlaceholder1(canvas, "", currentDate, margin + 60, startY+32, 0, font); replacePlaceholder1(canvas, "", currentDate, margin + 60, startY, 0, font); } // if (pageText.contains("${jcurrentDate}")) { // replacePlaceholder1(canvas, "${jcurrentDate}", currentDate, margin + 100, startY, 150, font); // startY -= lineHeight; // } // // if (pageText.contains("${ucurrentDate}")) { // replacePlaceholder1(canvas, "${ucurrentDate}", currentDate, margin + 100, startY, 300, font); // } } /** * 在PDF左上角添加图片 */ public static void addHeaderImageToPdf(PdfContentByte canvas, String templatePath, Rectangle pageSize) throws Exception { // 获取图片路径 String imagePath = templatePath + File.separator + "zczq.png"; File imageFile = new File(imagePath); // 如果使用相对路径找不到,尝试从resources获取 if (!imageFile.exists()) { String resourcePath = "D:/work/A-stock/src/main/resources/templates"; if (resourcePath.startsWith("/") && System.getProperty("os.name").toLowerCase().contains("windows")) { resourcePath = resourcePath.substring(1); } resourcePath = resourcePath.replaceAll("%20", " "); if (resourcePath.contains("file:")) { resourcePath = resourcePath.substring(resourcePath.indexOf("file:") + 5); } if (resourcePath.contains("!")) { resourcePath = resourcePath.substring(0, resourcePath.indexOf("!")); } imageFile = new File(resourcePath); } if (imageFile.exists()) { Image image = Image.getInstance(imageFile.getAbsolutePath()); // 设置图片大小 image.scaleToFit(100, 100); // 设置图片位置(左上角) image.setAbsolutePosition(370, pageSize.getHeight() - 194); canvas.addImage(image); } else { log.warn("未找到图片文件: {}", imagePath); } } /** * 替换单个占位符 */ public static void replacePlaceholder1(PdfContentByte canvas, String placeholder, String value, float x, float y, float width, Font font) { // 添加白色背景覆盖占位符区域 canvas.saveState(); canvas.setColorFill(BaseColor.WHITE); canvas.rectangle(x - 5, y - 15, width, 20); canvas.fill(); canvas.restoreState(); // 添加新文本 ColumnText.showTextAligned(canvas, Element.ALIGN_LEFT, new Phrase(value, font), x, y, 0); } /** * 从PDF模板生成新的PDF,替换占位符 */ private void generatePdfFromTemplate(File templatePdf, File outputPdf, User user) throws Exception { PdfReader reader = new PdfReader(new FileInputStream(templatePdf)); PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(outputPdf)); // 设置中文字体 BaseFont baseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED); Font font = new Font(baseFont, 12, Font.NORMAL); Font boldFont = new Font(baseFont, 12, Font.BOLD); SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日"); String currentDate = sdf.format(new Date()); // 准备替换的数据 String realName = user.getRealName() != null ? user.getRealName() : ""; String idCard = user.getIdCard() != null ? user.getIdCard() : ""; String address = user.getRegAddress() != null ? user.getRegAddress() : ""; // 获取PDF页数 int pageCount = reader.getNumberOfPages(); // 在每一页上查找并替换占位符 for (int pageNum = 1; pageNum <= pageCount; pageNum++) { PdfContentByte canvas = stamper.getOverContent(pageNum); Rectangle pageSize = reader.getPageSize(pageNum); // 提取PDF文本查找占位符位置 String pageText = PdfTextExtractor.getTextFromPage(reader, pageNum, new SimpleTextExtractionStrategy()); // 在PDF上查找并替换占位符 replacePlaceholdersInPdf(canvas, pageSize, pageText, realName, idCard, address, currentDate, font,pageNum); } stamper.close(); reader.close(); } /** * 在PDF上替换占位符(使用文本覆盖方式) */ private void replacePlaceholdersInPdf(PdfContentByte canvas, Rectangle pageSize, String pageText, String realName, String idCard, String address, String currentDate, Font font,int pageNum) throws Exception { // 查找占位符在文本中的位置,然后估算在PDF中的坐标 // 由于PDF坐标系统复杂,这里使用固定位置替换 // 实际使用时需要根据PDF模板的具体布局调整坐标 float margin = 50; float lineHeight = 14; float startY = pageSize.getHeight() - 194; if(pageNum == 1){ replacePlaceholder(canvas, "", realName, margin + 75, startY, 0, font); startY -= lineHeight; replacePlaceholder(canvas, "", address, margin + 75, startY-2, 0, font); startY -= lineHeight; replacePlaceholder(canvas, "", idCard, margin + 95, startY-2, 0, font); } if(pageNum == 3){ replacePlaceholder(canvas, "", currentDate, margin + 60, startY+32, 0, font); replacePlaceholder(canvas, "", currentDate, margin + 60, startY, 0, font); } } /** * 替换单个占位符 */ private void replacePlaceholder(PdfContentByte canvas, String placeholder, String value, float x, float y, float width, Font font) { // 添加白色背景覆盖占位符区域 canvas.saveState(); canvas.setColorFill(BaseColor.WHITE); canvas.rectangle(x - 5, y - 15, width, 20); canvas.fill(); canvas.restoreState(); // 添加新文本 ColumnText.showTextAligned(canvas, Element.ALIGN_LEFT, new Phrase(value, font), x, y, 0); } @Override public void viewAgreementPdf(HttpServletRequest request, HttpServletResponse response) { try { User user = iUserService.getCurrentUser(request); if (user == null) { response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "用户未登录"); return; } String pdfDir = PropertiesUtil.getProperty("agreement.pdf.dir", System.getProperty("user.dir") + "/agreement_pdf"); String pdfFileName = "agreement_" + user.getId() + ".pdf"; File pdfFile = new File(pdfDir, pdfFileName); if (!pdfFile.exists()) { response.sendError(HttpServletResponse.SC_NOT_FOUND, "协议文件不存在,请先生成协议"); return; } response.setContentType("application/pdf"); response.setHeader("Content-Disposition", "inline; filename=" + pdfFileName); FileInputStream fis = new FileInputStream(pdfFile); OutputStream os = response.getOutputStream(); byte[] buffer = new byte[4096]; int bytesRead; while ((bytesRead = fis.read(buffer)) != -1) { os.write(buffer, 0, bytesRead); } fis.close(); os.flush(); os.close(); } catch (Exception e) { log.error("查看用户协议PDF失败", e); try { response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "查看PDF失败"); } catch (IOException ex) { log.error("发送错误响应失败", ex); } } } }