|
@@ -0,0 +1,302 @@
|
|
|
|
|
+package com.hotent.project.service;
|
|
|
|
|
+
|
|
|
|
|
+import org.apache.pdfbox.pdmodel.PDDocument;
|
|
|
|
|
+import org.apache.poi.xwpf.usermodel.XWPFDocument;
|
|
|
|
|
+import org.apache.poi.xwpf.usermodel.XWPFParagraph;
|
|
|
|
|
+import org.apache.poi.xwpf.usermodel.XWPFRun;
|
|
|
|
|
+import org.apache.poi.xwpf.usermodel.BreakType;
|
|
|
|
|
+
|
|
|
|
|
+import java.io.File;
|
|
|
|
|
+import java.io.FileInputStream;
|
|
|
|
|
+import java.io.FileOutputStream;
|
|
|
|
|
+import java.util.ArrayList;
|
|
|
|
|
+import java.util.List;
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 卷宗生成测试类(不依赖Spring)
|
|
|
|
|
+ */
|
|
|
|
|
+public class ArchiveTest {
|
|
|
|
|
+
|
|
|
|
|
+ public static void main(String[] args) throws Exception {
|
|
|
|
|
+ System.out.println("========== 文件名称提取 ==========");
|
|
|
|
|
+ List<String> fileUrls = extractFileNames();
|
|
|
|
|
+
|
|
|
|
|
+ System.out.println("\n========== 页数计算 ==========");
|
|
|
|
|
+ int totalPages = calculateAllPageCount(fileUrls);
|
|
|
|
|
+
|
|
|
|
|
+ System.out.println("\n========== 卷宗生成 ==========");
|
|
|
|
|
+ generateArchive(fileUrls);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 提取文件名称
|
|
|
|
|
+ */
|
|
|
|
|
+ private static List<String> extractFileNames() {
|
|
|
|
|
+ String[] fileUrls = {
|
|
|
|
|
+ "D:\\fx\\cc\\7778、成本监审集体审议记录20251216101702575.docx",
|
|
|
|
|
+ "D:\\fx\\cc\\成本审核模板_2025_12_16_14_34_56.xlsx",
|
|
|
|
|
+ "D:\\fx\\cc\\文书文件20251216141325913.pdf"
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ List<String> validFiles = new ArrayList<>();
|
|
|
|
|
+ for (String url : fileUrls) {
|
|
|
|
|
+ String fileName = extractFileName(url);
|
|
|
|
|
+ String fileType = getFileType(url);
|
|
|
|
|
+ File file = new File(url);
|
|
|
|
|
+ String status = file.exists() ? "✓" : "✗";
|
|
|
|
|
+ System.out.println(status + " | " + fileName + " | " + fileType);
|
|
|
|
|
+ if (file.exists()) {
|
|
|
|
|
+ validFiles.add(url);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return validFiles;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 提取文件名
|
|
|
|
|
+ */
|
|
|
|
|
+ private static String extractFileName(String url) {
|
|
|
|
|
+ if (url == null || url.isEmpty()) {
|
|
|
|
|
+ return "";
|
|
|
|
|
+ }
|
|
|
|
|
+ int lastSlash = url.lastIndexOf('/');
|
|
|
|
|
+ return lastSlash >= 0 ? url.substring(lastSlash + 1) : url;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 获取文件类型
|
|
|
|
|
+ */
|
|
|
|
|
+ private static String getFileType(String url) {
|
|
|
|
|
+ String fileName = extractFileName(url);
|
|
|
|
|
+ if (fileName.endsWith(".pdf")) {
|
|
|
|
|
+ return "PDF";
|
|
|
|
|
+ } else if (fileName.endsWith(".docx")) {
|
|
|
|
|
+ return "Word";
|
|
|
|
|
+ } else if (fileName.endsWith(".xlsx")) {
|
|
|
|
|
+ return "Excel";
|
|
|
|
|
+ }
|
|
|
|
|
+ return "Unknown";
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 计算所有文件的页数
|
|
|
|
|
+ */
|
|
|
|
|
+ private static int calculateAllPageCount(List<String> fileUrls) {
|
|
|
|
|
+ int totalPages = 0;
|
|
|
|
|
+ for (String filePath : fileUrls) {
|
|
|
|
|
+ int pageCount = calculatePageCount(filePath);
|
|
|
|
|
+ String fileName = extractFileName(filePath);
|
|
|
|
|
+ System.out.println(fileName + " -> " + pageCount + " 页");
|
|
|
|
|
+ totalPages += pageCount;
|
|
|
|
|
+ }
|
|
|
|
|
+ System.out.println("总页数: " + totalPages);
|
|
|
|
|
+ return totalPages;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 计算单个文件页数
|
|
|
|
|
+ */
|
|
|
|
|
+ private static int calculatePageCount(String filePath) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ if (filePath == null || filePath.isEmpty()) {
|
|
|
|
|
+ return 0;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ String lowerCase = filePath.toLowerCase();
|
|
|
|
|
+
|
|
|
|
|
+ if (lowerCase.endsWith(".doc") || lowerCase.endsWith(".docx")) {
|
|
|
|
|
+ return getWordPageCount(filePath);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ return 1;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ System.out.println(" [警告] 无法读取页数: " + e.getMessage());
|
|
|
|
|
+ return 1;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 获取Word文档的页数
|
|
|
|
|
+ */
|
|
|
|
|
+ private static int getWordPageCount(String filePath) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ FileInputStream fis = new FileInputStream(filePath);
|
|
|
|
|
+ XWPFDocument doc = new XWPFDocument(fis);
|
|
|
|
|
+ int pages = doc.getProperties().getExtendedProperties().getUnderlyingProperties().getPages();
|
|
|
|
|
+ doc.close();
|
|
|
|
|
+ fis.close();
|
|
|
|
|
+ return pages > 0 ? pages : 1;
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ System.out.println(" [警告] 无法读取Word页数: " + e.getMessage());
|
|
|
|
|
+ return 1;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 生成卷宗
|
|
|
|
|
+ */
|
|
|
|
|
+ private static void generateArchive(List<String> fileUrls) throws Exception {
|
|
|
|
|
+ XWPFDocument document = new XWPFDocument();
|
|
|
|
|
+ boolean isFirst = true;
|
|
|
|
|
+
|
|
|
|
|
+ for (String filePath : fileUrls) {
|
|
|
|
|
+ String fileName = extractFileName(filePath);
|
|
|
|
|
+ String lowerCase = filePath.toLowerCase();
|
|
|
|
|
+
|
|
|
|
|
+ if (!isFirst) {
|
|
|
|
|
+ XWPFParagraph pageBreak = document.createParagraph();
|
|
|
|
|
+ XWPFRun run = pageBreak.createRun();
|
|
|
|
|
+ run.addBreak(BreakType.PAGE);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (lowerCase.endsWith(".docx") || lowerCase.endsWith(".doc")) {
|
|
|
|
|
+ mergeWordDocument(document, filePath);
|
|
|
|
|
+ } else if (lowerCase.endsWith(".pdf")) {
|
|
|
|
|
+ mergePdfDocument(document, filePath);
|
|
|
|
|
+ } else if (lowerCase.endsWith(".xlsx") || lowerCase.endsWith(".xls")) {
|
|
|
|
|
+ mergeExcelDocument(document, filePath);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ isFirst = false;
|
|
|
|
|
+ System.out.println("✓ 已添加: " + fileName);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ String outputPath = "D:\\fx\\cc\\卷宗_" + System.currentTimeMillis() + ".docx";
|
|
|
|
|
+ FileOutputStream fos = new FileOutputStream(outputPath);
|
|
|
|
|
+ document.write(fos);
|
|
|
|
|
+ fos.close();
|
|
|
|
|
+ document.close();
|
|
|
|
|
+
|
|
|
|
|
+ System.out.println("\n✓ 卷宗生成成功!");
|
|
|
|
|
+ System.out.println("输出路径: " + outputPath);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 合并Word文档
|
|
|
|
|
+ */
|
|
|
|
|
+ private static void mergeWordDocument(XWPFDocument document, String filePath) throws Exception {
|
|
|
|
|
+ FileInputStream fis = new FileInputStream(filePath);
|
|
|
|
|
+ XWPFDocument sourceDoc = new XWPFDocument(fis);
|
|
|
|
|
+
|
|
|
|
|
+ org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBody srcBody = sourceDoc.getDocument().getBody();
|
|
|
|
|
+ org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBody destBody = document.getDocument().getBody();
|
|
|
|
|
+
|
|
|
|
|
+ for (org.apache.xmlbeans.XmlObject obj : srcBody.selectPath("./*")) {
|
|
|
|
|
+ if (obj instanceof org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP) {
|
|
|
|
|
+ org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP newP = destBody.addNewP();
|
|
|
|
|
+ newP.set(obj.copy());
|
|
|
|
|
+ } else if (obj instanceof org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl) {
|
|
|
|
|
+ org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl newTbl = destBody.addNewTbl();
|
|
|
|
|
+ newTbl.set(obj.copy());
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ sourceDoc.close();
|
|
|
|
|
+ fis.close();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 合并PDF文档
|
|
|
|
|
+ */
|
|
|
|
|
+ private static void mergePdfDocument(XWPFDocument document, String filePath) throws Exception {
|
|
|
|
|
+ try {
|
|
|
|
|
+ PDDocument pdfDoc = PDDocument.load(new File(filePath));
|
|
|
|
|
+ org.apache.pdfbox.rendering.PDFRenderer renderer = new org.apache.pdfbox.rendering.PDFRenderer(pdfDoc);
|
|
|
|
|
+ int pageCount = pdfDoc.getNumberOfPages();
|
|
|
|
|
+ System.out.println(" PDF页数: " + pageCount);
|
|
|
|
|
+
|
|
|
|
|
+ for (int i = 0; i < pageCount; i++) {
|
|
|
|
|
+ java.awt.image.BufferedImage image = renderer.renderImageWithDPI(i, 200);
|
|
|
|
|
+ System.out.println(" 正在转换第 " + (i + 1) + " 页...");
|
|
|
|
|
+
|
|
|
|
|
+ java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream();
|
|
|
|
|
+ javax.imageio.ImageIO.write(image, "png", baos);
|
|
|
|
|
+ byte[] imageBytes = baos.toByteArray();
|
|
|
|
|
+ baos.close();
|
|
|
|
|
+
|
|
|
|
|
+ XWPFParagraph para = document.createParagraph();
|
|
|
|
|
+ XWPFRun run = para.createRun();
|
|
|
|
|
+ java.io.ByteArrayInputStream bais = new java.io.ByteArrayInputStream(imageBytes);
|
|
|
|
|
+ run.addPicture(bais, org.apache.poi.xwpf.usermodel.Document.PICTURE_TYPE_PNG,
|
|
|
|
|
+ "pdf_page_" + i + ".png", org.apache.poi.util.Units.toEMU(410), org.apache.poi.util.Units.toEMU(600));
|
|
|
|
|
+ bais.close();
|
|
|
|
|
+
|
|
|
|
|
+ para.createRun().addBreak();
|
|
|
|
|
+
|
|
|
|
|
+ if (i < pageCount - 1) {
|
|
|
|
|
+ XWPFParagraph pageBreak = document.createParagraph();
|
|
|
|
|
+ XWPFRun pageBreakRun = pageBreak.createRun();
|
|
|
|
|
+ pageBreakRun.addBreak(BreakType.PAGE);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ pdfDoc.close();
|
|
|
|
|
+ System.out.println(" PDF转换完成");
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ System.out.println(" [错误] PDF合并失败: " + e.getMessage());
|
|
|
|
|
+ e.printStackTrace();
|
|
|
|
|
+ XWPFParagraph para = document.createParagraph();
|
|
|
|
|
+ XWPFRun run = para.createRun();
|
|
|
|
|
+ run.setText("[PDF文件: " + new File(filePath).getName() + " - 转换失败]");
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 合并Excel文档
|
|
|
|
|
+ */
|
|
|
|
|
+ private static void mergeExcelDocument(XWPFDocument document, String filePath) throws Exception {
|
|
|
|
|
+ try {
|
|
|
|
|
+ org.apache.poi.ss.usermodel.Workbook workbook = org.apache.poi.ss.usermodel.WorkbookFactory.create(new File(filePath));
|
|
|
|
|
+
|
|
|
|
|
+ for (int sheetIndex = 0; sheetIndex < workbook.getNumberOfSheets(); sheetIndex++) {
|
|
|
|
|
+ org.apache.poi.ss.usermodel.Sheet sheet = workbook.getSheetAt(sheetIndex);
|
|
|
|
|
+
|
|
|
|
|
+ if (sheet.getPhysicalNumberOfRows() == 0) continue;
|
|
|
|
|
+
|
|
|
|
|
+ int rows = sheet.getPhysicalNumberOfRows();
|
|
|
|
|
+ int cols = 0;
|
|
|
|
|
+ for (int i = 0; i < rows; i++) {
|
|
|
|
|
+ org.apache.poi.ss.usermodel.Row row = sheet.getRow(i);
|
|
|
|
|
+ if (row != null && row.getPhysicalNumberOfCells() > cols) {
|
|
|
|
|
+ cols = row.getPhysicalNumberOfCells();
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (cols == 0) cols = 1;
|
|
|
|
|
+
|
|
|
|
|
+ org.apache.poi.xwpf.usermodel.XWPFTable table = document.createTable(rows, cols);
|
|
|
|
|
+ table.setStyleID("TableGrid");
|
|
|
|
|
+
|
|
|
|
|
+ for (int i = 0; i < rows; i++) {
|
|
|
|
|
+ org.apache.poi.ss.usermodel.Row excelRow = sheet.getRow(i);
|
|
|
|
|
+ org.apache.poi.xwpf.usermodel.XWPFTableRow wordRow = table.getRow(i);
|
|
|
|
|
+
|
|
|
|
|
+ if (excelRow != null) {
|
|
|
|
|
+ for (int j = 0; j < cols; j++) {
|
|
|
|
|
+ org.apache.poi.ss.usermodel.Cell cell = excelRow.getCell(j);
|
|
|
|
|
+ String cellValue = cell != null ? cell.toString() : "";
|
|
|
|
|
+
|
|
|
|
|
+ org.apache.poi.xwpf.usermodel.XWPFTableCell wordCell = wordRow.getCell(j);
|
|
|
|
|
+ wordCell.setText(cellValue);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (sheetIndex < workbook.getNumberOfSheets() - 1) {
|
|
|
|
|
+ XWPFParagraph pageBreak = document.createParagraph();
|
|
|
|
|
+ XWPFRun pageBreakRun = pageBreak.createRun();
|
|
|
|
|
+ pageBreakRun.addBreak(BreakType.PAGE);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ workbook.close();
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ System.out.println(" [警告] Excel合并失败: " + e.getMessage());
|
|
|
|
|
+ XWPFParagraph para = document.createParagraph();
|
|
|
|
|
+ XWPFRun run = para.createRun();
|
|
|
|
|
+ run.setText("[Excel文件: " + new File(filePath).getName() + " - 无法嵌入]");
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|