From 20075cb3a8bafa3144e2ffb78588fe80302134fe Mon Sep 17 00:00:00 2001 From: caihaohan Date: Sat, 30 Dec 2023 15:49:36 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=96=87=E4=BB=B6=E9=A2=84=E8=A7=88?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E5=8A=A0=E6=B0=B4=E5=8D=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- laws-module-system/pom.xml | 5 + .../system/controller/CommonController.java | 70 +++++++++++++- .../modules/system/util/SysWaterMarkUtil.java | 94 +++++++++++++++++++ 3 files changed, 168 insertions(+), 1 deletion(-) create mode 100644 laws-module-system/src/main/java/com/jero/modules/system/util/SysWaterMarkUtil.java diff --git a/laws-module-system/pom.xml b/laws-module-system/pom.xml index 1c6c8743..d1245fb5 100644 --- a/laws-module-system/pom.xml +++ b/laws-module-system/pom.xml @@ -72,6 +72,11 @@ spire.doc.free 5.2.0 + + org.apache.pdfbox + pdfbox + 2.0.6 + diff --git a/laws-module-system/src/main/java/com/jero/modules/system/controller/CommonController.java b/laws-module-system/src/main/java/com/jero/modules/system/controller/CommonController.java index 90560c9d..732feec8 100644 --- a/laws-module-system/src/main/java/com/jero/modules/system/controller/CommonController.java +++ b/laws-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 com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; @@ -10,6 +11,7 @@ import com.jero.common.system.api.ISysBaseAPI; 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 org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; @@ -50,6 +52,9 @@ public class CommonController { @Resource private IOSSFileService ossFileService; + @Resource + private SysWaterMarkUtil sysWaterMarkUtil; + @Value(value = "${jero.path.upload}") private String uploadpath; @@ -157,7 +162,7 @@ public class CommonController { */ @GetMapping(value = "/view/{id}") public void view(@PathVariable String id,HttpServletRequest request, HttpServletResponse response) { - downloadAndView(id, response); + downloadAndViewWithWaterMark(id, response); } private void downloadAndView(@PathVariable String id, HttpServletResponse response) { @@ -224,6 +229,69 @@ public class CommonController { } } + private void downloadAndViewWithWaterMark(@PathVariable String id, HttpServletResponse response) { + // 查询数据表数据是否存在 + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(OSSFile::getId, id); + OSSFile ossFile = ossFileService.getOne(queryWrapper); + if (null == ossFile) { + throw new JeroBootException("文件不存在.."); + } + String fileUrl = ossFile.getUrl(); + // minio 下载 + // 通过MinioUtil查询时 只需要桶后面的路径 + String minioUrl = MinioUtil.getMinioUrl(); + // Linux/unix 系统下文件路径分隔符为"/" 获取minio与存储桶的路径 + minioUrl = minioUrl + MinioUtil.getBucketName() + "/"; + String url = fileUrl.replace(minioUrl, ""); + // 文件名称 + String fileName = ossFile.getFileName(); + response.addHeader("Content-Disposition", "attachment;fileName=" + new String(fileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1)); + // 设置强制下载不打开 + response.setContentType("application/force-download"); + // 然后在您的controller方法中: + if ("pdf".equalsIgnoreCase(FileUtil.extName(fileName))) { + try (InputStream originalInputStream = MinioUtil.getMinioFile(MinioUtil.getBucketName(), url); + InputStream watermarkedInputStream = sysWaterMarkUtil.addWatermarkToPdf(originalInputStream); + OutputStream outputStream = response.getOutputStream()) { + + if (originalInputStream == null) { + return; + } + + byte[] buf = new byte[1024]; + int len; + while ((len = watermarkedInputStream.read(buf)) > 0) { + outputStream.write(buf, 0, len); + } + response.flushBuffer(); + + } catch (Exception e) { + log.error(e.getMessage()); + response.setStatus(404); + e.printStackTrace(); + } + } else { + try (InputStream inputStream = MinioUtil.getMinioFile(MinioUtil.getBucketName(), url); + OutputStream outputStream = response.getOutputStream() + ) { + byte[] buf = new byte[1024]; + int len; + if(inputStream==null) { + return; + } + while ((len = inputStream.read(buf)) > 0) { + outputStream.write(buf, 0, len); + } + response.flushBuffer(); + } catch (Exception e){ + log.error(e.getMessage()); + response.setStatus(404); + e.printStackTrace(); + } + } + } + private void setResponse(HttpServletResponse response, String fileName) { response.addHeader("Content-Disposition", "attachment;fileName=" + new String(fileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1)); // 设置强制下载不打开 diff --git a/laws-module-system/src/main/java/com/jero/modules/system/util/SysWaterMarkUtil.java b/laws-module-system/src/main/java/com/jero/modules/system/util/SysWaterMarkUtil.java new file mode 100644 index 00000000..a375fb7c --- /dev/null +++ b/laws-module-system/src/main/java/com/jero/modules/system/util/SysWaterMarkUtil.java @@ -0,0 +1,94 @@ +package com.jero.modules.system.util; + +import com.jero.modules.system.entity.SysUser; +import com.jero.modules.system.service.ISysUserService; +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.springframework.core.io.ClassPathResource; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.awt.*; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; + +/** + * 水印工具类 + * @author CaiHaohan + */ +@Component +public class SysWaterMarkUtil { + + @Resource + private ISysUserService userEoService; + + public String getWaterMarkConfig() { + LocalDate currentDate = LocalDate.now(); + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd"); + String formattedDate = currentDate.format(formatter); + + SysUser user = userEoService.getById(UserUtils.getUserId()); + String userName = user.calcNameWorkNo(); + + return userName + " " + formattedDate; + } + + public synchronized InputStream addWatermarkToPdf(InputStream inputStream) throws IOException { + String watermarkText = getWaterMarkConfig(); + PDDocument document = PDDocument.load(inputStream); + + // 设置水印字体、字体大小、颜色和透明度 + ClassPathResource fontResource = new ClassPathResource("fonts/SourceHanSerif-VF.ttf"); + PDType0Font font = PDType0Font.load(document, fontResource.getInputStream()); + float fontSize = 13.0f; + Color color = new Color(100, 100, 100, 0); + PDExtendedGraphicsState graphicsState = new PDExtendedGraphicsState(); + graphicsState.setNonStrokingAlphaConstant(0.4f); + graphicsState.setStrokingAlphaConstant(0.4f); + + // 遍历每一页并添加水印 + for (PDPage page : document.getPages()) { + // 获取页面尺寸以计算水印位置 + PDRectangle pageSize = page.getMediaBox(); + float xStep = pageSize.getWidth() / 4; + float yStep = pageSize.getHeight() / 4; + float rotationInRadians = (float) Math.toRadians(20); + + for (float xPosition = pageSize.getLowerLeftX(); xPosition <= pageSize.getWidth(); xPosition += xStep) { + for (float yPosition = pageSize.getLowerLeftY(); yPosition <= pageSize.getHeight(); yPosition += yStep) { + // 创建内容流并设置图形状态参数 + try (PDPageContentStream contentStream = new PDPageContentStream(document, page, PDPageContentStream.AppendMode.APPEND, true, true)) { + contentStream.setGraphicsStateParameters(graphicsState); + contentStream.setFont(font, fontSize); + contentStream.setNonStrokingColor(color); + contentStream.beginText(); + contentStream.setRenderingMode(RenderingMode.FILL); + // 设置水印文本的旋转和位置 + contentStream.setTextMatrix(Matrix.getRotateInstance(rotationInRadians, xPosition, yPosition)); + contentStream.showText(watermarkText); + contentStream.endText(); + } + } + } + } + + // 创建一个临时的ByteArrayOutputStream保存修改过的PDF + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + document.save(baos); + document.close(); + + // 将ByteArrayOutputStream转换为ByteArrayInputStream以供返回 + return new ByteArrayInputStream(baos.toByteArray()); + } + +}