diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/common/utils/PdfBoxQrCodeGenerator.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/common/utils/PdfBoxQrCodeGenerator.java index 123130d6..8e16e9d8 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/common/utils/PdfBoxQrCodeGenerator.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/common/utils/PdfBoxQrCodeGenerator.java @@ -219,16 +219,11 @@ public class PdfBoxQrCodeGenerator { + // 固定的边距(点) + private static final float MARGIN = 10.0f; + // 二维码大小比例(页面宽高中较小值的20%) + private static final float QR_SIZE_RATIO = 0.2f; - - - - - - - /** - * 在PDF每一页的指定位置添加二维码并返回数据流(二维码放大10倍,居中放置,带边界检查) - */ public static ByteArrayOutputStream addQRCodeToPDFOnAllPages(String srcPdf, byte[] qrCodeBytes, boolean isChangeFile) throws IOException { @@ -263,50 +258,37 @@ public class PdfBoxQrCodeGenerator { for (int pageNum = 1; pageNum <= numberOfPages; pageNum++) { PdfPage page = pdfDoc.getPage(pageNum); - // 获取页面的实际可见区域(裁剪框) + // 获取页面的所有边界框信息 + Rectangle mediaBox = page.getMediaBox(); Rectangle cropBox = page.getCropBox(); - if (cropBox == null) { - cropBox = page.getPageSize(); - } - float pageWidth = cropBox.getWidth(); - float pageHeight = cropBox.getHeight(); + // 使用CropBox作为主要参考,因为它定义了页面的可见区域 + Rectangle visibleArea = (cropBox != null) ? cropBox : mediaBox; + + // 计算页面宽高中较小的值 + float minDimension = Math.min(visibleArea.getWidth(), visibleArea.getHeight()); + + // 动态计算二维码大小(页面宽高中较小值的20%) + float qrSize = minDimension * QR_SIZE_RATIO; // 输出页面尺寸信息 - System.out.println("页面 " + pageNum + " 宽度: " + pageWidth + ", 高度: " + pageHeight); + System.out.println("页面 " + pageNum + " 尺寸: " + visibleArea.getWidth() + "x" + visibleArea.getHeight()); + System.out.println("页面 " + pageNum + " 二维码大小 (点): " + qrSize); - // 根据页面大小动态计算二维码尺寸(页面宽度的15%) - float qrSize = pageWidth * 0.15f; + // 计算左上角的位置(PDF坐标系:原点在左下角) + float qrX = visibleArea.getLeft() + MARGIN; + float qrY = visibleArea.getTop() - qrSize - MARGIN; - // 设置边距(页面宽度的2%) - float margin = pageWidth * 0.02f; - - // 计算二维码位置 - 左上角 - // 注意:PDF坐标系的原点在左下角,所以Y坐标需要从页面高度减去二维码高度和边距 - float qrX = cropBox.getLeft() + margin; - float qrY = cropBox.getTop() - qrSize - margin; + // 打印二维码位置信息 + System.out.println("页面 " + pageNum + " 左上角二维码位置: x=" + qrX + ", y=" + qrY); try { - // 使用最简单的方法:直接添加图像 - addQRCodeSimple(pdfDoc, page, qrCodeBytes, qrX, qrY, qrSize); + // 使用Canvas API添加左上角二维码 + addQRCodeWithCanvas(pdfDoc, page, qrCodeBytes, qrX, qrY, qrSize); } catch (Exception e) { System.err.println("在页面 " + pageNum + " 添加二维码时出错: " + e.getMessage()); e.printStackTrace(); - - // 尝试使用Canvas方法作为备用 - try { - addQRCodeWithCanvas(pdfDoc, page, qrCodeBytes, qrX, qrY, qrSize, cropBox); - } catch (Exception ex) { - System.err.println("Canvas备用方法也失败: " + ex.getMessage()); - - // 最后尝试使用原始大小 - try { - addQRCodeSimple(pdfDoc, page, qrCodeBytes, qrX, qrY, 50); // 使用固定大小 - } catch (Exception ex2) { - System.err.println("最简单方法也失败: " + ex2.getMessage()); - } - } } } @@ -314,89 +296,44 @@ public class PdfBoxQrCodeGenerator { return pdfOut; } - // 使用Canvas的备用方法 + // 使用Canvas API添加图像 private static void addQRCodeWithCanvas(PdfDocument pdfDoc, PdfPage page, - byte[] qrCodeBytes, float x, float y, float size, Rectangle pageSize) throws IOException { + byte[] qrCodeBytes, float x, float y, float size) throws IOException { - PdfCanvas pdfCanvas = new PdfCanvas(page.newContentStreamAfter(), page.getResources(), pdfDoc); - try (Canvas canvas = new Canvas(pdfCanvas, pageSize)) { - ImageData imageData = ImageDataFactory.create(qrCodeBytes); - com.itextpdf.layout.element.Image image = new com.itextpdf.layout.element.Image(imageData); + // 创建Canvas对象 - 使用PdfPage和Rectangle构造函数 + Canvas canvas = new Canvas(page, page.getPageSize()); - // 设置二维码尺寸和位置 - image.scaleAbsolute(size, size); - image.setFixedPosition(x, y); - - // 设置透明度确保不会被背景遮挡 - image.setOpacity(0.9f); - - canvas.add(image); - } - } - - // 最简单的方法:使用原始图像大小 - private static void addQRCodeSimple(PdfDocument pdfDoc, PdfPage page, - byte[] qrCodeBytes, float x, float y, float size) throws IOException { - - PdfCanvas canvas = new PdfCanvas(page.newContentStreamAfter(), page.getResources(), pdfDoc); - - // 创建图像对象 + // 创建图像数据 ImageData imageData = ImageDataFactory.create(qrCodeBytes); - com.itextpdf.kernel.pdf.xobject.PdfImageXObject imageXObject = - new com.itextpdf.kernel.pdf.xobject.PdfImageXObject(imageData); - // 添加图像到指定位置(使用原始大小) - canvas.addXObjectAt(imageXObject, x, y); + // 创建Image对象 + Image image = new Image(imageData); - canvas.release(); + // 设置图像位置和大小 + image.setFixedPosition(x, y); + image.setWidth(size); + image.setHeight(size); + + // 添加图像到Canvas + canvas.add(image); + + // 关闭Canvas + canvas.close(); + + System.out.println("Canvas方法设置位置: x=" + x + ", y=" + y); } - public static void simpleTest(String pdfPath, String outputPath, byte[] qrCodeBytes) { - try { - PdfDocument pdfDoc = new PdfDocument(new PdfReader(pdfPath), new PdfWriter(outputPath)); - - for (int i = 1; i <= pdfDoc.getNumberOfPages(); i++) { - PdfPage page = pdfDoc.getPage(i); - Rectangle rect = page.getPageSize(); - - // 简单地在左上角添加一个固定大小的二维码 - PdfCanvas canvas = new PdfCanvas(page.newContentStreamAfter(), page.getResources(), pdfDoc); - - ImageData imageData = ImageDataFactory.create(qrCodeBytes); - com.itextpdf.kernel.pdf.xobject.PdfImageXObject imageXObject = - new com.itextpdf.kernel.pdf.xobject.PdfImageXObject(imageData); - - // 固定位置和大小 - float x = 20; // 固定X位置 - float y = rect.getHeight() - 70; // 固定Y位置 - - canvas.addXObjectAt(imageXObject, x, y); - canvas.release(); - } - - pdfDoc.close(); - System.out.println("简单测试完成"); - } catch (Exception e) { - e.printStackTrace(); - } - } - -// public static void main(String[] args) { -// String path = "C:\\Users\\YuanJie\\Desktop\\test.pdf"; -// String outputPath = "C:\\Users\\YuanJie\\Desktop\\test1.pdf"; -// String params = "http://192.168.110.151:7788/codeDetail?id=" + "1957649652924448769"; -// byte[] bytes = PdfBoxQrCodeGenerator.generateQRCodeBytes(params); -// simpleTest(path, outputPath, bytes); -// } - -// 如果使用带放大倍数参数的方法,需要修改main方法: + // main方法示例 public static void main(String[] args) { - //合规性手续业务流 test 测试101_101 - String path = "C:\\Users\\YuanJie\\Desktop\\合规性手续业务流.pdf"; + + String path = "C:\\Users\\YuanJie\\Desktop\\test.pdf"; String outputPath = "C:\\Users\\YuanJie\\Desktop\\test1.pdf"; String params = "http://192.168.110.151:7788/codeDetail?id=" + "1957649652924448769"; - byte[] bytes = PdfBoxQrCodeGenerator.generateQRCodeBytes(params); + BufferedImage image = QrCodeUtil.generate(params, 200, 200); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + ImgUtil.write(image, ImgUtil.IMAGE_TYPE_PNG, out); + byte[] bytes = out.toByteArray(); try { System.out.println("二维码字节大小: " + bytes.length + " 字节"); @@ -407,9 +344,8 @@ public class PdfBoxQrCodeGenerator { System.out.println("二维码图片已保存到桌面,用于验证二维码是否生成正确"); } - // 在每一页添加二维码,放大10倍 - ByteArrayOutputStream byteArrayOutputStream = - PdfBoxQrCodeGenerator.addQRCodeToPDFOnAllPages(path, bytes, false); + // 在每一页添加二维码 + ByteArrayOutputStream byteArrayOutputStream = addQRCodeToPDFOnAllPages(path, bytes, false); try (FileOutputStream fileOut = new FileOutputStream(outputPath)) { byteArrayOutputStream.writeTo(fileOut); @@ -447,6 +383,12 @@ public class PdfBoxQrCodeGenerator { + + + + + +