From dd30506fe9b4c22da87f5f63877c9df10aff7d01 Mon Sep 17 00:00:00 2001
From: jiangs <373297395@qq.com>
Date: Fri, 28 Nov 2025 09:09:49 +0800
Subject: [PATCH] =?UTF-8?q?pdf=E6=8A=A5=E5=91=8AA4=E5=88=87=E5=89=B2A5?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
lis-interfaceCommon/pom.xml | 6 +
.../utils/PdfPaperConverter.java | 114 ++++++++++++++++++
pom.xml | 8 ++
.../service/impl/ZybgcxServcieImpl.java | 24 ++--
4 files changed, 144 insertions(+), 8 deletions(-)
create mode 100644 lis-interfaceCommon/src/main/java/com/czlis/interfaceCommon/utils/PdfPaperConverter.java
diff --git a/lis-interfaceCommon/pom.xml b/lis-interfaceCommon/pom.xml
index dc457d0..2a92d71 100644
--- a/lis-interfaceCommon/pom.xml
+++ b/lis-interfaceCommon/pom.xml
@@ -75,6 +75,12 @@
spring-boot-starter-websocket
+
+ org.apache.pdfbox
+ pdfbox
+
+
+
diff --git a/lis-interfaceCommon/src/main/java/com/czlis/interfaceCommon/utils/PdfPaperConverter.java b/lis-interfaceCommon/src/main/java/com/czlis/interfaceCommon/utils/PdfPaperConverter.java
new file mode 100644
index 0000000..776a293
--- /dev/null
+++ b/lis-interfaceCommon/src/main/java/com/czlis/interfaceCommon/utils/PdfPaperConverter.java
@@ -0,0 +1,114 @@
+package com.czlis.interfaceCommon.utils;
+
+import org.apache.pdfbox.pdmodel.PDDocument;
+import org.apache.pdfbox.pdmodel.PDPage;
+import org.apache.pdfbox.pdmodel.PDPageContentStream;
+import org.apache.pdfbox.pdmodel.common.PDRectangle;
+import org.apache.pdfbox.multipdf.LayerUtility;
+import org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.util.Base64;
+
+public class PdfPaperConverter {
+
+ private static final float A4_WIDTH = 595f; // A4标准宽度(pt)
+ private static final float A4_HEIGHT = 842f; // A4标准高度(pt)
+ private static final float A5_HEIGHT = 420f; // A5高度(保留A4宽度)
+ private static final float TOLERANCE = 10f; // 尺寸判断容差
+
+
+ // 新增:粗略判断Base64 PDF是A4还是A5(高度> A5_HEIGHT即视为A4)
+ public static boolean isBase64PdfA4(String base64Pdf) {
+ if (base64Pdf == null || base64Pdf.trim().isEmpty()) {
+ return false; // 空字符串直接返回非A4
+ }
+
+ byte[] pdfBytes = null;
+ try {
+ // 尝试解码Base64(失败则视为非A4)
+ pdfBytes = cn.hutool.core.codec.Base64.decode(base64Pdf);
+ } catch (Exception e) {
+ return false;
+ }
+
+ try (PDDocument doc = PDDocument.load(new ByteArrayInputStream(pdfBytes))) {
+ if (doc.getNumberOfPages() == 0) {
+ return false; // 无页面视为非A4
+ }
+ // 获取第一页高度(粗略判断:大于A5高度即认为是A4)
+ PDPage firstPage = doc.getPage(0);
+ float pageHeight = firstPage.getMediaBox().getHeight();
+ return pageHeight > A5_HEIGHT; // 核心判断逻辑
+ } catch (Exception e) {
+ // PDF损坏、加载失败等异常,均视为非A4(粗略判断容错)
+ return false;
+ }
+ }
+
+ public static String convertBase64PdfToA5IfConfigured(String base64Pdf, String configuredSize) throws Exception {
+ if ("A4".equalsIgnoreCase(configuredSize)) {
+ return base64Pdf;
+ }
+
+ byte[] pdfBytes = cn.hutool.core.codec.Base64.decode(base64Pdf);
+ try (PDDocument originalDoc = PDDocument.load(new ByteArrayInputStream(pdfBytes))) {
+ if (originalDoc.getNumberOfPages() == 0) {
+ return base64Pdf; // 空文档直接返回
+ }
+
+ PDPage firstPage = originalDoc.getPage(0);
+ PDRectangle mediaBox = firstPage.getMediaBox();
+ boolean isA4 = isClose(mediaBox.getWidth(), A4_WIDTH) && isClose(mediaBox.getHeight(), A4_HEIGHT);
+
+ if (isA4) {
+ return cropA4ToA5(originalDoc); // 仅A4文档执行裁剪
+ }
+
+ return base64Pdf;
+ }
+ }
+
+ private static boolean isClose(float a, float b) {
+ return Math.abs(a - b) <= TOLERANCE;
+ }
+
+ private static String cropA4ToA5(PDDocument originalDoc) throws Exception {
+ try (PDDocument newDoc = new PDDocument()) {
+ for (int i = 0; i < originalDoc.getNumberOfPages(); i++) {
+ cropPage(originalDoc, newDoc, i);
+ }
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ newDoc.save(baos);
+ return Base64.getEncoder().encodeToString(baos.toByteArray());
+ }
+ }
+
+ // 最终终极适配:2.0.29两参数importPageAsForm + 平移 + 双框同步,无空白、不切顶
+ private static void cropPage(PDDocument sourceDoc, PDDocument targetDoc, int pageIndex) throws Exception {
+ PDPage sourcePage = sourceDoc.getPage(pageIndex);
+ PDRectangle sourceMediaBox = sourcePage.getMediaBox();
+ float targetWidth = sourceMediaBox.getWidth(); // 保留A4原宽度
+ float targetHeight = A5_HEIGHT; // A5高度
+ float yOffset = -(A4_HEIGHT - targetHeight); // 向下平移距离(关键:让上半部分落入可视区)
+
+ // 1. 新建A5页面:同步设置mediaBox(物理尺寸)和cropBox(可视区),避免空白
+ PDPage targetPage = new PDPage();
+ PDRectangle targetBox = new PDRectangle(0f, 0f, targetWidth, targetHeight);
+ targetPage.setMediaBox(targetBox);
+ targetPage.setCropBox(targetBox);
+ targetDoc.addPage(targetPage);
+
+ // 2. 2.0.29兼容:仅用两参数导入整个原页面
+ LayerUtility layerUtil = new LayerUtility(targetDoc);
+ PDFormXObject form = layerUtil.importPageAsForm(sourceDoc, pageIndex); // 仅两个参数,2.0.29支持
+
+ // 3. 平移绘制:让原页面上半部分显示在新页面中
+ try (PDPageContentStream contentStream = new PDPageContentStream(targetDoc, targetPage)) {
+ // cm指令:向下平移247pt(A4_HEIGHT - A5_HEIGHT),原页面上半部分(247~842pt)对应新页面(0~595pt)
+ contentStream.appendRawCommands(String.format("1 0 0 1 0 %.2f cm\n", yOffset));
+ contentStream.drawForm(form);
+ }
+ }
+}
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 9662477..206eccd 100644
--- a/pom.xml
+++ b/pom.xml
@@ -45,6 +45,7 @@
2.1.7
1.5-beta1
7.2.5
+ 2.0.29
9.0.112
@@ -358,6 +359,13 @@
${itextpdf.version}
+
+ org.apache.pdfbox
+ pdfbox
+ ${pdfbox.version}
+
+
+
diff --git a/zybgcx/src/main/java/com/czlis/zybgcx/service/impl/ZybgcxServcieImpl.java b/zybgcx/src/main/java/com/czlis/zybgcx/service/impl/ZybgcxServcieImpl.java
index 074f189..b5d33d1 100644
--- a/zybgcx/src/main/java/com/czlis/zybgcx/service/impl/ZybgcxServcieImpl.java
+++ b/zybgcx/src/main/java/com/czlis/zybgcx/service/impl/ZybgcxServcieImpl.java
@@ -1,20 +1,17 @@
package com.czlis.zybgcx.service.impl;
import cn.hutool.core.codec.Base64;
-import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
-import cn.hutool.core.io.FileUtil;
-import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
import com.czlis.common.config.RuoYiConfig;
import com.czlis.common.core.domain.Result;
import com.czlis.common.core.domain.entity.lis.LabPat;
import com.czlis.common.core.domain.entity.lis.LabReqreportPdffile;
import com.czlis.common.utils.file.FileUtils;
-import com.czlis.common.utils.ip.IpUtils;
import com.czlis.common.utils.uuid.UUID;
import com.czlis.interfaceCommon.utils.CommonUtil;
import com.czlis.interfaceCommon.utils.LisUtil;
+import com.czlis.interfaceCommon.utils.PdfPaperConverter;
import com.czlis.interfaceCommon.utils.ReportUtil;
import com.czlis.zybgcx.mapper.ZybgcxMapper;
import com.czlis.zybgcx.pojo.Web_fs_printReport;
@@ -24,13 +21,10 @@ import com.czlis.zybgcx.pojo.Web_result;
import com.czlis.zybgcx.service.ZybgcxService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
-import org.springframework.web.bind.annotation.CrossOrigin;
-import javax.print.PrintException;
+
import java.io.File;
-import java.io.FileInputStream;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;
@@ -106,6 +100,20 @@ public class ZybgcxServcieImpl implements ZybgcxService {
//过滤A5格式报告单
List