diff --git a/jero-boot-base/jero-boot-base-core/pom.xml b/jero-boot-base/jero-boot-base-core/pom.xml
index 1ccfaceb..5914a0d4 100644
--- a/jero-boot-base/jero-boot-base-core/pom.xml
+++ b/jero-boot-base/jero-boot-base-core/pom.xml
@@ -276,6 +276,10 @@
p6spy
p6spy
+
+ org.apache.pdfbox
+ pdfbox
+
\ No newline at end of file
diff --git a/jero-boot-module-system/src/main/java/com/jero/modules/system/controller/CommonController.java b/jero-boot-module-system/src/main/java/com/jero/modules/system/controller/CommonController.java
index a4285d31..b0a40b6b 100644
--- a/jero-boot-module-system/src/main/java/com/jero/modules/system/controller/CommonController.java
+++ b/jero-boot-module-system/src/main/java/com/jero/modules/system/controller/CommonController.java
@@ -1,5 +1,6 @@
package com.jero.modules.system.controller;
+import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
@@ -9,6 +10,7 @@ import com.jero.common.system.vo.LoginUser;
import com.jero.common.util.*;
import com.jero.modules.oss.entity.OSSFile;
import com.jero.modules.oss.service.IOSSFileService;
+import com.jero.modules.system.util.SysWaterMarkUtil;
import lombok.extern.slf4j.Slf4j;
import com.jero.common.api.vo.Result;
import com.jero.common.constant.CommonConstant;
@@ -74,6 +76,8 @@ public class CommonController {
*/
@Value(value="${jero.fileSuffixLimits}")
private String[] fileSuffixLimits;
+ @Resource
+ private SysWaterMarkUtil sysWaterMarkUtil;
/**
* @Author 政辉
@@ -227,6 +231,10 @@ public class CommonController {
fileName = ossFile.getFileName();
inputStream = MinioUtil.getMinioFile(MinioUtil.getBucketName(), url);
}
+ //pdf加水印
+ if ("pdf".equalsIgnoreCase(FileUtil.extName(fileName))) {
+ inputStream = sysWaterMarkUtil.addWatermarkToPdf(inputStream);
+ }
response.addHeader("Content-Disposition", "attachment;fileName=" + new String(fileName.getBytes("UTF-8"),"iso-8859-1"));
response.setContentType("application/force-download");// 设置强制下载不打开
if (type == null) {
@@ -264,9 +272,8 @@ public class CommonController {
ossFileService.updateAndPush(ossFile);
}
} catch (IOException e) {
- log.error("预览文件失败" + e.getMessage());
+ log.error("预览文件失败" + e);
response.setStatus(404);
- e.printStackTrace();
} finally {
if (inputStream != null) {
try {
@@ -402,7 +409,10 @@ public class CommonController {
fileName = ossFile.getFileName();
inputStream = MinioUtil.getMinioFile(MinioUtil.getBucketName(), url);
}
-
+ //pdf加水印
+ if ("pdf".equalsIgnoreCase(FileUtil.extName(fileName))) {
+ inputStream = sysWaterMarkUtil.addWatermarkToPdf(inputStream);
+ }
ossFileService.updateById(ossFile);
LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
//if (loginUser.getIsCompanyUser()) {
@@ -449,9 +459,8 @@ public class CommonController {
ossFileService.updateAndPush(ossFile);
}
} catch (IOException e) {
- log.error("预览文件失败" + e.getMessage());
+ log.error("预览文件失败" + e);
response.setStatus(404);
- e.printStackTrace();
} finally {
if (inputStream != null) {
try {
diff --git a/jero-boot-module-system/src/main/java/com/jero/modules/system/util/SysWaterMarkUtil.java b/jero-boot-module-system/src/main/java/com/jero/modules/system/util/SysWaterMarkUtil.java
new file mode 100644
index 00000000..42a98d6e
--- /dev/null
+++ b/jero-boot-module-system/src/main/java/com/jero/modules/system/util/SysWaterMarkUtil.java
@@ -0,0 +1,153 @@
+package com.jero.modules.system.util;
+
+import com.jero.common.system.vo.LoginUser;
+import com.jero.common.util.DateUtils;
+import lombok.extern.slf4j.Slf4j;
+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.pdmodel.font.PDType0Font;
+import org.apache.pdfbox.pdmodel.graphics.state.PDExtendedGraphicsState;
+import org.apache.pdfbox.pdmodel.graphics.state.RenderingMode;
+import org.apache.pdfbox.util.Matrix;
+import org.apache.shiro.SecurityUtils;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.stereotype.Component;
+
+import java.awt.*;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 水印工具类
+ *
+ * @author CaiHaohan
+ */
+@Component
+@Slf4j
+public class SysWaterMarkUtil {
+
+ @Value("${watermark.font-size}")
+ private float fontSize;
+
+ @Value("${watermark.color.r}")
+ private int r;
+
+ @Value("${watermark.color.g}")
+ private int g;
+
+ @Value("${watermark.color.b}")
+ private int b;
+
+ @Value("${watermark.color.a}")
+ private int a;
+
+ @Value("${watermark.lineNumPerPage}")
+ private int lineNumPerPage;
+
+ @Value("${watermark.columnNumPerPage}")
+ private int columnNumPerPage;
+
+ @Value("${watermark.degree}")
+ private int degree;
+
+ @Value("${watermark.margin.left}")
+ private float marginLeft;
+
+ @Value("${watermark.margin.top}")
+ private float marginTop;
+ @Value("${watermark.dateFormat}")
+ private String dateFormat;
+
+
+ public List getWaterMarkConfig() {
+ LoginUser loginUser = UserUtils.getLoginUser();
+
+ Date curDate = new Date();
+ String cudDateStr = DateUtils.date2Str(curDate, new SimpleDateFormat(dateFormat));
+ List result = new ArrayList<>();
+ if (loginUser == null) {
+ result.add("汽车标准化工作平台 ");
+ }else {
+ result.add("汽车标准化工作平台 " + loginUser.getRealname());
+ }
+
+ result.add(cudDateStr);
+ return result;
+ }
+
+ public synchronized InputStream addWatermarkToPdf(InputStream inputStream) throws IOException {
+ List watermarkText = getWaterMarkConfig();
+ PDDocument document = PDDocument.load(inputStream);
+ document.setAllSecurityToBeRemoved(true);
+ // 加载水印字体
+ ClassPathResource fontResource = new ClassPathResource("fonts/SourceHanSerif-VF.ttf");
+ PDType0Font font = PDType0Font.load(document, fontResource.getInputStream());
+
+ // 设置水印颜色和透明度
+ Color color = new Color(r, g, b, a);
+ PDExtendedGraphicsState graphicsState = new PDExtendedGraphicsState();
+ graphicsState.setNonStrokingAlphaConstant(0.4f);
+ graphicsState.setStrokingAlphaConstant(0.4f);
+
+ // 遍历每一页并添加水印
+ for (PDPage page : document.getPages()) {
+ // 获取页面尺寸以计算水印位置和大小
+ PDRectangle pageSize = page.getMediaBox();
+ float pageWidth = pageSize.getWidth();
+ float pageHeight = pageSize.getHeight();
+
+ // 根据页面宽度动态调整字体大小
+ float dynamicFontSize = pageWidth * (this.fontSize / 595); // 假设基准页面宽度为595单位
+
+ float xStep = pageWidth / columnNumPerPage;
+ float yStep = pageHeight / lineNumPerPage;
+ float rotationInRadians = (float) Math.toRadians(degree);
+
+ // 行间距,设为字体大小的一半
+ float lineSpacing = dynamicFontSize / 2;
+
+ // 计算两行文本的总高度
+ float totalTextHeight = (dynamicFontSize + lineSpacing) * (watermarkText.size() - 1);
+
+ for (float xPosition = pageSize.getLowerLeftX() + marginLeft; xPosition <= pageWidth - marginLeft; xPosition += xStep) {
+ for (float yPosition = pageSize.getLowerLeftY() + marginTop; yPosition <= pageHeight - marginTop; yPosition += yStep) {
+ try (PDPageContentStream contentStream = new PDPageContentStream(document, page, PDPageContentStream.AppendMode.APPEND, true, true)) {
+ contentStream.setGraphicsStateParameters(graphicsState);
+ contentStream.setNonStrokingColor(color);
+
+ float textYPosition = yPosition + (totalTextHeight / 2);
+
+ for (String line : watermarkText) {
+ contentStream.beginText();
+ contentStream.setFont(font, dynamicFontSize);
+ contentStream.setRenderingMode(RenderingMode.FILL);
+ contentStream.setTextMatrix(Matrix.getRotateInstance(rotationInRadians, xPosition, textYPosition));
+ contentStream.showText(line);
+ contentStream.endText();
+
+ // 更新文本的Y坐标,为下一行准备
+ textYPosition -= (dynamicFontSize + lineSpacing);
+ }
+ }
+ }
+ }
+ }
+
+ // 创建一个临时的ByteArrayOutputStream保存修改过的PDF
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ document.save(baos);
+ document.close();
+
+ // 将ByteArrayOutputStream转换为ByteArrayInputStream以供返回
+ return new ByteArrayInputStream(baos.toByteArray());
+ }
+}
diff --git a/jero-boot-module-system/src/main/java/com/jero/modules/system/util/UserUtils.java b/jero-boot-module-system/src/main/java/com/jero/modules/system/util/UserUtils.java
new file mode 100644
index 00000000..96c5ae83
--- /dev/null
+++ b/jero-boot-module-system/src/main/java/com/jero/modules/system/util/UserUtils.java
@@ -0,0 +1,36 @@
+package com.jero.modules.system.util;
+
+import com.jero.common.system.vo.LoginUser;
+import org.apache.shiro.SecurityUtils;
+import org.apache.shiro.UnavailableSecurityManagerException;
+import org.apache.shiro.session.InvalidSessionException;
+
+public class UserUtils {
+
+ /**
+ * 获取当前登录用户ID
+ *
+ */
+ public static String getUserId() {
+ String userId = null;
+ try {
+ LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
+ if(sysUser!=null){
+ userId = sysUser.getId();
+ }
+ } catch (UnavailableSecurityManagerException e) {
+ e.printStackTrace();
+ } catch (InvalidSessionException e) {
+ e.printStackTrace();
+ }
+ return userId;
+ }
+
+ /**
+ * 获取当前登录用户
+ *
+ */
+ public static LoginUser getLoginUser() {
+ return (LoginUser) SecurityUtils.getSubject().getPrincipal();
+ }
+}
diff --git a/jero-boot-module-system/src/main/resources/fonts/SourceHanSerif-VF.ttf b/jero-boot-module-system/src/main/resources/fonts/SourceHanSerif-VF.ttf
new file mode 100644
index 00000000..021fc0db
Binary files /dev/null and b/jero-boot-module-system/src/main/resources/fonts/SourceHanSerif-VF.ttf differ
diff --git a/jero-boot-single-startup/src/main/resources/application-dev.yml b/jero-boot-single-startup/src/main/resources/application-dev.yml
index 61e50750..6bf405e9 100644
--- a/jero-boot-single-startup/src/main/resources/application-dev.yml
+++ b/jero-boot-single-startup/src/main/resources/application-dev.yml
@@ -363,4 +363,26 @@ template:
#入会申请表word
applicationWord: E:\\biao_zhun_suo\\template\\applicationWord.docx
#模版目录
- templatePath: D:\\hzwl\\income_payments\\income_payments_managerment\\template\\
\ No newline at end of file
+ templatePath: D:\\hzwl\\income_payments\\income_payments_managerment\\template\\
+
+# 水印配置项
+watermark:
+ font-size: 13.0
+ # 每页几行
+ lineNumPerPage: 8
+ # 每页几列
+ columnNumPerPage: 3
+ # 倾斜角度
+ degree: 30
+ # 颜色
+ color:
+ r: 180
+ g: 180
+ b: 180
+ a: 1
+ # 页边距
+ margin:
+ top: 100
+ left: 60
+ # 日期格式
+ dateFormat: yyyy-MM-dd HH:mm:ss
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 6f5249e8..6dd3a345 100644
--- a/pom.xml
+++ b/pom.xml
@@ -278,6 +278,11 @@
p6spy
3.9.1
+
+ org.apache.pdfbox
+ pdfbox
+ 2.0.27
+