| @ -0,0 +1,266 @@ | |||
| package com.hxhq.business.utils; | |||
| import com.hxhq.business.domain.StudyMethod; | |||
| import com.hxhq.business.domain.StudyMethodRead; | |||
| import com.hxhq.common.core.utils.DateUtils; | |||
| import com.hxhq.common.security.utils.SecurityUtils; | |||
| import com.itextpdf.text.*; | |||
| import com.itextpdf.text.pdf.*; | |||
| import org.slf4j.Logger; | |||
| import org.slf4j.LoggerFactory; | |||
| import org.springframework.beans.factory.annotation.Value; | |||
| import org.springframework.stereotype.Component; | |||
| import java.io.File; | |||
| import java.io.FileOutputStream; | |||
| import java.io.IOException; | |||
| import java.nio.file.Paths; | |||
| import java.util.*; | |||
| import java.util.List; | |||
| /** | |||
| * OpenPDF工具类 - 支持保存到本地文件 | |||
| */ | |||
| @Component | |||
| public class StudyMethodFileUtil { | |||
| private static final Logger log = LoggerFactory.getLogger(StudyMethodFileUtil.class); | |||
| /** | |||
| * 资源映射路径 前缀 | |||
| */ | |||
| @Value("${file.prefix}") | |||
| public String localFilePrefix; | |||
| /** | |||
| * 域名或本机访问地址 | |||
| */ | |||
| @Value("${file.domain}") | |||
| public String domain; | |||
| /** | |||
| * 上传文件存储在本地的根路径 | |||
| */ | |||
| @Value("${file.path}") | |||
| private String localFilePath; | |||
| public String exportStudyMethodFile(StudyMethod studyMethod, List<StudyMethodRead> list) { | |||
| String fileUrl = studyMethod.getFileUrl(); | |||
| fileUrl = fileUrl.replaceFirst(localFilePrefix, ""); | |||
| int indexOf = fileUrl.lastIndexOf("/"); | |||
| String path = fileUrl.substring(0, indexOf); | |||
| String exportFileName = exportTable(SecurityUtils.getNickName() + DateUtils.dateTimeNow(DateUtils.YYYY_MM_DD_HH_MM_SS), list, | |||
| localFilePath + fileUrl, localFilePath + File.separator + path); | |||
| return localFilePrefix + path + File.separator + exportFileName; | |||
| } | |||
| /** | |||
| * 复制原有PDF的所有页面到新Document中 | |||
| */ | |||
| private static void copyOriginalPagesToDocument(Document doc, PdfWriter writer, PdfReader reader) throws DocumentException { | |||
| int pageCount = reader.getNumberOfPages(); | |||
| PdfContentByte canvas = writer.getDirectContent(); // 获取直接内容画布 | |||
| for (int i = 1; i <= pageCount; i++) { | |||
| doc.newPage(); // 新建一页(与原PDF页面一一对应) | |||
| // 5.5.11中通过PdfImportedPage导入原有页面 | |||
| PdfImportedPage importedPage = writer.getImportedPage(reader, i); | |||
| // 将原有页面绘制到新文档的当前页 | |||
| canvas.addTemplate(importedPage, 0, 0); | |||
| } | |||
| } | |||
| /** | |||
| * 导出table | |||
| * @param headerText | |||
| * @param fileDir | |||
| * @return | |||
| */ | |||
| public static String exportTable(String headerText, List<StudyMethodRead> list, String SRC_PDF, String fileDir) { | |||
| Document document = null; | |||
| FileOutputStream fos = null; | |||
| String filePath = ""; | |||
| String fileName = ""; | |||
| try { | |||
| // 1. 生成文件名 | |||
| fileName = generateFileName(); | |||
| // 2. 确保目录存在 | |||
| File dir = new File(fileDir); | |||
| if (!dir.exists()) { | |||
| dir.mkdirs(); | |||
| } | |||
| // 3. 完整文件路径 | |||
| filePath = Paths.get(fileDir, fileName).toString(); | |||
| // 创建PDF文档 设置文档边距,避免内容遮挡页眉页脚 | |||
| // 1. 读取原有PDF,获取页面尺寸(保证新文档与原文档格式一致) | |||
| PdfReader srcReader = new PdfReader(SRC_PDF); | |||
| Rectangle pageSize = srcReader.getPageSize(1); // 取第一页尺寸作为新文档尺寸 | |||
| // 2. 初始化Document(iText 5的核心高层类) | |||
| document = new Document(pageSize); | |||
| fos = new FileOutputStream(filePath); | |||
| // 3. 关联PdfWriter,绑定Document和输出流(5.5.11必须先创建Writer再open Document) | |||
| PdfWriter writer = PdfWriter.getInstance(document, fos); | |||
| // 设置页面事件,每页添加文字页眉 | |||
| writer.setPageEvent(new TextHeaderEvent(headerText)); | |||
| // 4. 设置PDF属性 | |||
| document.addTitle("华西海圻"); | |||
| document.addAuthor("华西海圻"); | |||
| document.addCreator("华西海圻"); | |||
| document.addCreationDate(); | |||
| document.open(); | |||
| // 5. 复制原有PDF的所有页面到新Document中 | |||
| copyOriginalPagesToDocument(document, writer, srcReader); | |||
| // 6. 设置中文字体 | |||
| BaseFont bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED); | |||
| Font headerFont = new Font(bfChinese, 12, Font.BOLD); | |||
| Font contentFont = new Font(bfChinese, 10, Font.NORMAL); | |||
| // 7. 表格设置到新的一页 | |||
| document.newPage(); | |||
| // 8. 创建表格 | |||
| PdfPTable table = new PdfPTable(4); | |||
| table.setWidthPercentage(100); | |||
| table.setSpacingBefore(10); | |||
| // 9. 表头 | |||
| String[] headers = {"签名人", "签名意义", "签名时间", "备注"}; | |||
| for (String header : headers) { | |||
| PdfPCell cell = new PdfPCell(new Phrase(header, headerFont)); | |||
| cell.setHorizontalAlignment(Element.ALIGN_CENTER); | |||
| cell.setBackgroundColor(BaseColor.WHITE); | |||
| cell.setPadding(8); | |||
| cell.setBorderWidth(1); | |||
| table.addCell(cell); | |||
| } | |||
| // 10. 表格数据 | |||
| int rowNum = 0; | |||
| for (StudyMethodRead studyMethodRead : list) { | |||
| // 交替行颜色 | |||
| if (rowNum % 2 == 0) { | |||
| table.getDefaultCell().setBackgroundColor(BaseColor.WHITE); | |||
| } else { | |||
| table.getDefaultCell().setBackgroundColor(BaseColor.WHITE); | |||
| } | |||
| table.addCell(createCell(studyMethodRead.getQmrMc(), contentFont)); | |||
| table.addCell(createCell(studyMethodRead.getQmyy(), contentFont)); | |||
| table.addCell(createCell(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, studyMethodRead.getCreateTime()), contentFont)); | |||
| table.addCell(createCell(studyMethodRead.getRemark(), contentFont)); | |||
| rowNum++; | |||
| } | |||
| document.add(table); | |||
| log.info("生成成功:{}", filePath); | |||
| } catch (Exception e) { | |||
| log.error("生成失败", e); | |||
| throw new RuntimeException("生成失败: " + e.getMessage()); | |||
| } finally { | |||
| if (document != null) { | |||
| document.close(); | |||
| } | |||
| if (fos != null) { | |||
| try { | |||
| fos.close(); | |||
| } catch (IOException e) { | |||
| log.error("关闭文件流失败", e); | |||
| } | |||
| } | |||
| } | |||
| return fileName; | |||
| } | |||
| /** | |||
| * 创建表格 | |||
| */ | |||
| private static PdfPCell createCell(String content, Font font) { | |||
| PdfPCell cell = new PdfPCell(new Phrase(content, font)); | |||
| cell.setHorizontalAlignment(Element.ALIGN_CENTER); | |||
| cell.setVerticalAlignment(Element.ALIGN_MIDDLE); | |||
| cell.setPadding(6); | |||
| cell.setMinimumHeight(25); | |||
| return cell; | |||
| } | |||
| /** | |||
| * 生成文件名 | |||
| */ | |||
| private static String generateFileName() { | |||
| Random random= new Random(); | |||
| String timestamp = DateUtils.dateTimeNow("yyyyMMddHHmmss"); | |||
| return String.format("%s_%s.pdf", timestamp,random.nextInt(1000)); | |||
| } | |||
| /** | |||
| * 页面事件处理类 - 每页添加文字页眉 | |||
| */ | |||
| static class TextHeaderEvent extends PdfPageEventHelper { | |||
| private String headerText; | |||
| private BaseFont baseFont; | |||
| public TextHeaderEvent(String headerText) throws Exception { | |||
| this.headerText = headerText; | |||
| // 创建字体(支持中文) | |||
| this.baseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED); | |||
| } | |||
| @Override | |||
| public void onEndPage(PdfWriter writer, Document document) { | |||
| try { | |||
| // 获取页面尺寸 | |||
| Rectangle pageSize = document.getPageSize(); | |||
| float pageWidth = pageSize.getWidth(); | |||
| float pageHeight = pageSize.getHeight(); | |||
| // 设置页眉参数 | |||
| float topMargin = 15; // 顶部边距 | |||
| float fontSize = 10; // 字体大小 | |||
| // 计算文字宽度(用于居中) | |||
| float textWidth = baseFont.getWidthPoint(headerText, fontSize); | |||
| // 计算居中位置 | |||
| float textX = (pageWidth - textWidth) / 2; | |||
| float textY = pageHeight - topMargin; | |||
| // 获取画布 | |||
| PdfContentByte canvas = writer.getDirectContent(); | |||
| // 添加页眉文字 | |||
| canvas.beginText(); | |||
| canvas.setFontAndSize(baseFont, fontSize); | |||
| canvas.setTextMatrix(textX, textY); | |||
| canvas.showText(headerText); | |||
| canvas.endText(); | |||
| // 添加页眉分隔线(可选) | |||
| addHeaderLine(canvas, pageWidth, textY - 10); | |||
| } catch (Exception e) { | |||
| e.printStackTrace(); | |||
| } | |||
| } | |||
| private void addHeaderLine(PdfContentByte canvas, float pageWidth, float yPos) { | |||
| canvas.setLineWidth(0.5f); | |||
| canvas.moveTo(50, yPos); | |||
| canvas.lineTo(pageWidth - 50, yPos); | |||
| canvas.stroke(); | |||
| } | |||
| } | |||
| } | |||