pdf报告A4切割A5
This commit is contained in:
parent
6f0262ad04
commit
dd30506fe9
@ -75,6 +75,12 @@
|
||||
<artifactId>spring-boot-starter-websocket</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.pdfbox</groupId>
|
||||
<artifactId>pdfbox</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
|
||||
</dependencies>
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
8
pom.xml
8
pom.xml
@ -45,6 +45,7 @@
|
||||
<itext.version>2.1.7</itext.version>
|
||||
<barbecue.version>1.5-beta1</barbecue.version>
|
||||
<itextpdf.version>7.2.5</itextpdf.version>
|
||||
<pdfbox.version>2.0.29</pdfbox.version>
|
||||
|
||||
<!-- override dependency version -->
|
||||
<tomcat.version>9.0.112</tomcat.version>
|
||||
@ -358,6 +359,13 @@
|
||||
<version>${itextpdf.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.pdfbox</groupId>
|
||||
<artifactId>pdfbox</artifactId>
|
||||
<version>${pdfbox.version}</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
</dependencies>
|
||||
|
||||
|
||||
|
||||
@ -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<Map<String, Object>> collectA5 = bgdhBase64List.stream().filter(bgdhBase64 -> bgdhBase64.get("pageType").equals("A5")).collect(Collectors.toList());
|
||||
//其中有可能格式虽然是A5,实际尺寸是A4,需要进行处理
|
||||
for (Map<String, Object> stringObjectMap : collectA5) {
|
||||
String bas64Str = stringObjectMap.get("data").toString();
|
||||
if(!PdfPaperConverter.isBase64PdfA4(bas64Str)) continue;
|
||||
try {
|
||||
String base64_A5 = PdfPaperConverter.convertBase64PdfToA5IfConfigured(bas64Str, "A5");
|
||||
stringObjectMap.put("data", base64_A5);
|
||||
} catch (Exception e) {
|
||||
log.error("裁剪pdf出错:",e);
|
||||
return new Result("0","裁剪pdf出错!"+e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
log.info("collectA5:"+collectA5);
|
||||
|
||||
//对A5格式的报告单进行排序
|
||||
collectA5.sort(new Comparator<Map<String, Object>>() {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user