From d24bf731e0e13fb6a711b4d7b3e3946f3e067f7a Mon Sep 17 00:00:00 2001 From: xueqingkun Date: Thu, 5 Dec 2024 14:10:01 +0800 Subject: [PATCH] =?UTF-8?q?1.=20=E4=BF=AE=E6=94=B9=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E4=BF=A1=E6=81=AF=E4=BB=8EthreadLocal=E4=B8=AD=E8=8E=B7?= =?UTF-8?q?=E5=8F=96=202.=20=E6=8A=8A=E7=94=A8=E6=88=B7=E4=BF=A1=E6=81=AF?= =?UTF-8?q?=E5=86=99=E5=85=A5=E5=88=B0cookie=E4=B8=AD=203.=20=E4=B8=8B?= =?UTF-8?q?=E8=BD=BD=E7=9A=84=E5=9B=BE=E7=89=87=E6=88=96=E8=80=85pdf?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=B0=B4=E5=8D=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 12 ++ .../supervision/config/JwtInterceptor.java | 53 ++++- .../com/supervision/config/WebConfig.java | 2 +- .../minio/service/MinioService.java | 2 + .../minio/service/impl/MinioServiceImpl.java | 46 ++++- .../controller/CaseEvidenceController.java | 5 +- .../police/service/CaseEvidenceService.java | 5 +- .../service/impl/CaseEvidenceServiceImpl.java | 23 ++- .../java/com/supervision/utils/TokenUtil.java | 4 +- .../java/com/supervision/utils/UserUtil.java | 24 +-- .../com/supervision/utils/WatermarkUtil.java | 184 ++++++++++++++++++ .../com/supervision/demo/WordRenderTest.java | 84 +++++++- 12 files changed, 404 insertions(+), 40 deletions(-) create mode 100644 src/main/java/com/supervision/utils/WatermarkUtil.java diff --git a/pom.xml b/pom.xml index 8eb106a..198ec07 100644 --- a/pom.xml +++ b/pom.xml @@ -187,6 +187,18 @@ 1.2.83_noneautotype + + + com.itextpdf + itextpdf + 5.5.10 + + + + com.itextpdf + itext-asian + 5.2.0 + diff --git a/src/main/java/com/supervision/config/JwtInterceptor.java b/src/main/java/com/supervision/config/JwtInterceptor.java index 2e8fd02..cd2e3e7 100644 --- a/src/main/java/com/supervision/config/JwtInterceptor.java +++ b/src/main/java/com/supervision/config/JwtInterceptor.java @@ -6,6 +6,7 @@ import cn.hutool.json.JSONUtil; import cn.hutool.jwt.JWT; import cn.hutool.jwt.JWTUtil; import com.supervision.utils.TokenUtil; +import jakarta.servlet.http.Cookie; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; @@ -28,7 +29,7 @@ public class JwtInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { //请求消息头获取用户ID - String token = request.getHeader("token"); + String token = findTokenInRequest(request); if (StrUtil.isBlank(token)) { // 如果是swagger来的接口,说明这里是测试的,会伪造一个用户 String referer = request.getHeader("Referer"); @@ -36,13 +37,24 @@ public class JwtInterceptor implements HandlerInterceptor { cacheAuth(JWTUtil.parseToken(devActiveUser())); return true; } else { -// throw new BusinessException("当前用户未登录", HttpStatus.UNAUTHORIZED.value()); + throw new BusinessException("当前用户未登录", HttpStatus.UNAUTHORIZED.value()); } } -// JWT jwt = JWTUtil.parseToken(token); + JWT jwt = JWTUtil.parseToken(token); // 校验token是否过期,如果过期了,需要提示过期重新登录 -// checkTokenExpire(jwt); -// cacheAuth(jwt); + boolean expire = checkTokenExpire(jwt); + if (expire){ + throw new BusinessException("用户登录已过期,请重新登录", HttpStatus.UNAUTHORIZED.value()); + } + String cookieToken = findTokenInCookie(request.getCookies()); + if (!StrUtil.equals(cookieToken, token)){ + Cookie tokenCookie = new Cookie("token", token); + tokenCookie.setMaxAge((int) TokenUtil.EXPIRE_TIME); + tokenCookie.setPath("/"); + tokenCookie.setAttribute("SameSite", "Lax"); + response.addCookie(tokenCookie); + } + cacheAuth(jwt); return true; } @@ -55,15 +67,38 @@ public class JwtInterceptor implements HandlerInterceptor { HandlerInterceptor.super.afterCompletion(request, response, handler, ex); } + private String findTokenInRequest(HttpServletRequest request) { + String token = request.getHeader("token"); + if (StrUtil.isEmpty(token)) { + // 尝试从cookie中获取token数据 + token = findTokenInCookie(request.getCookies()); + } + return token; + } + - private void checkTokenExpire(JWT jwt) { + private String findTokenInCookie(Cookie[] cookies) { + if (cookies != null) { + for (Cookie cookie : cookies) { + if (cookie.getName().equals("token")) { + return cookie.getValue(); + } + } + } + return null; + } + + /** + * 校验token是否过期 + * @param jwt jwt + * @return true 过期,false未过期 + */ + private boolean checkTokenExpire(JWT jwt) { Object expireTime = jwt.getPayload("expireTime"); long l = Long.parseLong(String.valueOf(expireTime)); // 校验是否比当前时间大 long currentTimeMillis = System.currentTimeMillis(); - if (currentTimeMillis > l) { - throw new BusinessException("用户登录已过期,请重新登录", HttpStatus.UNAUTHORIZED.value()); - } + return currentTimeMillis > l; } diff --git a/src/main/java/com/supervision/config/WebConfig.java b/src/main/java/com/supervision/config/WebConfig.java index c2d8151..58a9cf3 100644 --- a/src/main/java/com/supervision/config/WebConfig.java +++ b/src/main/java/com/supervision/config/WebConfig.java @@ -27,7 +27,7 @@ public class WebConfig implements WebMvcConfigurer { paths.add("/error"); paths.add("/favicon.ico"); paths.add("/user/login"); - paths.add("/minio/downloadFile"); + // paths.add("/minio/downloadFile"); paths.add("/minio/uploadFile"); paths.add("/user/changePassWord"); paths.add("/fileManage/downloadFile"); diff --git a/src/main/java/com/supervision/minio/service/MinioService.java b/src/main/java/com/supervision/minio/service/MinioService.java index 404537d..0a6e524 100644 --- a/src/main/java/com/supervision/minio/service/MinioService.java +++ b/src/main/java/com/supervision/minio/service/MinioService.java @@ -17,6 +17,8 @@ public interface MinioService { void downloadFile(String fileId, HttpServletResponse response); + void downloadFileWithWatermark(String fileId, String fileType, String waterMarkName, HttpServletResponse response); + R delFile(String fileId); InputStream getObjectInputStream(String fileId); diff --git a/src/main/java/com/supervision/minio/service/impl/MinioServiceImpl.java b/src/main/java/com/supervision/minio/service/impl/MinioServiceImpl.java index 2a36eb2..15a0728 100644 --- a/src/main/java/com/supervision/minio/service/impl/MinioServiceImpl.java +++ b/src/main/java/com/supervision/minio/service/impl/MinioServiceImpl.java @@ -1,23 +1,32 @@ package com.supervision.minio.service.impl; import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.io.IoUtil; import cn.hutool.core.lang.Assert; +import cn.hutool.core.util.StrUtil; +import com.itextpdf.text.DocumentException; import com.supervision.common.domain.R; import com.supervision.common.utils.StringUtils; import com.supervision.minio.client.MinioTemplate; import com.supervision.minio.domain.MinioFile; import com.supervision.minio.mapper.MinioFileMapper; import com.supervision.minio.service.MinioService; +import com.supervision.utils.UserUtil; +import com.supervision.utils.WatermarkUtil; +import io.minio.StatObjectResponse; import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; +import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.*; +@Slf4j @Service @RequiredArgsConstructor public class MinioServiceImpl implements MinioService { @@ -60,7 +69,42 @@ public class MinioServiceImpl implements MinioService { public void downloadFile(String fileId, HttpServletResponse response) { MinioFile minioFile = minioFileMapper.selectById(fileId); String fileType = minioFile.getFileType(); - minioTemplate.getObject(bucketName, fileId, fileType, response); + this.downloadFileWithWatermark(fileId, fileType, UserUtil.getUser().getUserName(), response); + } + + + @Override + public void downloadFileWithWatermark(String fileId, String fileType, String waterMarkName, HttpServletResponse response) { + try { + InputStream inputStream = minioTemplate.getObjectInputStream(bucketName,fileId); + + StatObjectResponse statObjectResponse = minioTemplate.statObject(bucketName, fileId); + + String fileName = fileId + "." + fileType; + response.setHeader("Content-Disposition", "inline;filename=" + fileName); + response.setCharacterEncoding("UTF-8"); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + if (StrUtil.equalsIgnoreCase("pdf", fileType)){ + WatermarkUtil.pdfByText(inputStream, baos, waterMarkName, Map.of()); + response.setContentLengthLong(baos.size()); + response.setContentType(statObjectResponse.contentType()); + response.getOutputStream().write(baos.toByteArray()); + }else if (StrUtil.equalsAnyIgnoreCase(fileType,"jpg", "jpeg", "png","bmp")){ + WatermarkUtil.ImageByText(waterMarkName, inputStream, baos, Map.of("formatName", fileType)); + response.setContentType(statObjectResponse.contentType()); + response.setContentLengthLong(baos.size()); + response.getOutputStream().write(baos.toByteArray()); + }else { + response.setContentLengthLong(statObjectResponse.size()); + response.setContentType(statObjectResponse.contentType()); + IoUtil.copy(inputStream, response.getOutputStream()); + } + baos.close(); + inputStream.close(); + }catch (IOException | DocumentException e){ + log.error("文件下载失败", e); + } } @Override diff --git a/src/main/java/com/supervision/police/controller/CaseEvidenceController.java b/src/main/java/com/supervision/police/controller/CaseEvidenceController.java index 20be9dd..6700fce 100644 --- a/src/main/java/com/supervision/police/controller/CaseEvidenceController.java +++ b/src/main/java/com/supervision/police/controller/CaseEvidenceController.java @@ -2,6 +2,7 @@ package com.supervision.police.controller; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.Assert; +import com.itextpdf.text.DocumentException; import com.supervision.common.domain.R; import com.supervision.police.domain.EvidenceDirectory; import com.supervision.police.dto.*; @@ -16,6 +17,8 @@ import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.*; + +import java.io.IOException; import java.util.List; @@ -195,7 +198,7 @@ public class CaseEvidenceController { } @GetMapping("/downloadEvidence") - public void downloadEvidence(@RequestParam String evidenceId, HttpServletResponse response) { + public void downloadEvidence(@RequestParam String evidenceId, HttpServletResponse response) throws DocumentException, IOException { caseEvidenceService.downloadEvidence(evidenceId, response); } diff --git a/src/main/java/com/supervision/police/service/CaseEvidenceService.java b/src/main/java/com/supervision/police/service/CaseEvidenceService.java index 31ac6ab..a27f31a 100644 --- a/src/main/java/com/supervision/police/service/CaseEvidenceService.java +++ b/src/main/java/com/supervision/police/service/CaseEvidenceService.java @@ -2,6 +2,7 @@ package com.supervision.police.service; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.service.IService; +import com.itextpdf.text.DocumentException; import com.supervision.police.domain.CaseEvidence; import com.supervision.police.domain.EvidenceDirectory; import com.supervision.police.domain.EvidenceFile; @@ -11,6 +12,8 @@ import com.supervision.police.vo.EvidenceDirectoryReqVO; import com.supervision.police.vo.VerifyEvidenceReqVO; import jakarta.servlet.http.HttpServletResponse; + +import java.io.IOException; import java.util.List; import java.util.Map; @@ -165,5 +168,5 @@ public interface CaseEvidenceService extends IService { void redoExtractAttributes(String caseId, List caseEvidences); - void downloadEvidence(String evidenceId, HttpServletResponse response); + void downloadEvidence(String evidenceId, HttpServletResponse response) throws IOException, DocumentException; } diff --git a/src/main/java/com/supervision/police/service/impl/CaseEvidenceServiceImpl.java b/src/main/java/com/supervision/police/service/impl/CaseEvidenceServiceImpl.java index 23f481c..11c2436 100644 --- a/src/main/java/com/supervision/police/service/impl/CaseEvidenceServiceImpl.java +++ b/src/main/java/com/supervision/police/service/impl/CaseEvidenceServiceImpl.java @@ -13,6 +13,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.PageDTO; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.itextpdf.text.DocumentException; import com.supervision.common.constant.EvidenceConstants; import com.supervision.common.constant.IndexRuleConstants; import com.supervision.minio.domain.MinioFile; @@ -23,6 +24,8 @@ import com.supervision.police.mapper.CaseEvidenceMapper; import com.supervision.police.service.*; import com.supervision.police.vo.EvidenceDirectoryReqVO; import com.supervision.police.vo.VerifyEvidenceReqVO; +import com.supervision.utils.UserUtil; +import com.supervision.utils.WatermarkUtil; import com.supervision.utils.ZipFileUtil; import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; @@ -34,6 +37,8 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.text.SimpleDateFormat; @@ -956,15 +961,25 @@ public class CaseEvidenceServiceImpl extends ServiceImpl evidenceFileDTOList = evidenceFileService.listFileInfo(List.of(evidenceId)); Map fileInputStreamMap = new HashMap<>(); - evidenceFileDTOList.forEach(evidenceFileDTO -> { + for (EvidenceFileDTO evidenceFileDTO : evidenceFileDTOList) { MinioFile minioFile = minioService.getMinioFile(evidenceFileDTO.getFileId()); if (null != minioFile) { - fileInputStreamMap.put(minioFile.getFilename(), minioService.getObjectInputStream(minioFile)); + if (StrUtil.equalsAnyIgnoreCase(minioFile.getFileType(), "pdf")) { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + WatermarkUtil.pdfByText(minioService.getObjectInputStream(minioFile), bos, UserUtil.getUser().getUserName(), Map.of()); + fileInputStreamMap.put(minioFile.getFilename(), new ByteArrayInputStream(bos.toByteArray())); + } else if (StrUtil.equalsAnyIgnoreCase(minioFile.getFileType(), "jpg", "png", "jpeg", "bmp")) { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + WatermarkUtil.ImageByText(UserUtil.getUser().getUserName(), minioService.getObjectInputStream(minioFile), bos, Map.of("formatName", minioFile.getFileType())); + fileInputStreamMap.put(minioFile.getFilename(), new ByteArrayInputStream(bos.toByteArray())); + } else { + fileInputStreamMap.put(minioFile.getFilename(), minioService.getObjectInputStream(minioFile)); + } } - }); + } try { ZipFileUtil.createZipAndDownload(response, getById(evidenceId).getEvidenceName(), fileInputStreamMap); } catch (IOException e) { diff --git a/src/main/java/com/supervision/utils/TokenUtil.java b/src/main/java/com/supervision/utils/TokenUtil.java index 5542884..c05c043 100644 --- a/src/main/java/com/supervision/utils/TokenUtil.java +++ b/src/main/java/com/supervision/utils/TokenUtil.java @@ -8,11 +8,13 @@ import cn.hutool.jwt.signers.JWTSignerUtil; public class TokenUtil { + public static final long EXPIRE_TIME = 60 * 60 * 24; + public static String creatToken(String userInfo){ final JWTSigner signer = JWTSignerUtil.hs256("~~||DDEdfdfee33s6$$".getBytes()); JSONObject info = JSONUtil.parseObj(userInfo); // 过期时间一天,同时这个字段也作为单点登录使用 - info.putOnce("expireTime",System.currentTimeMillis() + 1000 * 60 * 60 * 24); + info.putOnce("expireTime",System.currentTimeMillis() + 1000 * EXPIRE_TIME); info.putOnce("issueTime",System.currentTimeMillis()); return JWTUtil.createToken(info, signer); } diff --git a/src/main/java/com/supervision/utils/UserUtil.java b/src/main/java/com/supervision/utils/UserUtil.java index c726913..32fc5cd 100644 --- a/src/main/java/com/supervision/utils/UserUtil.java +++ b/src/main/java/com/supervision/utils/UserUtil.java @@ -1,32 +1,16 @@ package com.supervision.utils; import cn.hutool.core.lang.Assert; -import cn.hutool.core.util.StrUtil; -import cn.hutool.json.JSONObject; import cn.hutool.json.JSONUtil; -import cn.hutool.jwt.JWT; -import cn.hutool.jwt.JWTUtil; +import com.supervision.config.ThreadCache; import com.supervision.police.dto.user.UserInfoDTO; -import jakarta.servlet.http.HttpServletRequest; -import org.springframework.web.context.request.RequestContextHolder; -import org.springframework.web.context.request.ServletRequestAttributes; public class UserUtil { public static UserInfoDTO getUser() { - ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); - Assert.notNull(requestAttributes, "未获取到用户信息"); - HttpServletRequest request = requestAttributes.getRequest(); - - String token = request.getHeader("token"); - if (StrUtil.isBlank(token)) { - token = (String) request.getAttribute("token"); - - } - Assert.notEmpty(token, "未获取到用户token信息"); - JWT jwt = JWTUtil.parseToken(token); - JSONObject claimsJson = jwt.getPayload().getClaimsJson(); - UserInfoDTO bean = JSONUtil.toBean(claimsJson.toString(), UserInfoDTO.class); + + String userString = ThreadCache.USER.get(); + UserInfoDTO bean = JSONUtil.toBean(userString, UserInfoDTO.class); Assert.notNull(bean, "未获取到用户信息"); return bean; } diff --git a/src/main/java/com/supervision/utils/WatermarkUtil.java b/src/main/java/com/supervision/utils/WatermarkUtil.java new file mode 100644 index 0000000..30a7eee --- /dev/null +++ b/src/main/java/com/supervision/utils/WatermarkUtil.java @@ -0,0 +1,184 @@ +package com.supervision.utils; + +import com.itextpdf.text.DocumentException; +import com.itextpdf.text.Element; +import com.itextpdf.text.pdf.*; + +import javax.imageio.ImageIO; +import javax.swing.*; +import java.awt.*; +import java.awt.image.BufferedImage; +import java.io.*; +import java.util.HashMap; +import java.util.Map; + +public class WatermarkUtil { + + private final static Map imageConfig = getImgDefaultConfig(); + + private final static Map pdfConfig = getPdfDefaultConfig(); + + public static Map getImgDefaultConfig(){ + + Map config = new HashMap<>(); + config.put("alpha",0.5f); // 水印透明度 + config.put("fontSize",28); // 水印文字大小 + config.put("font",new Font("微软雅黑", Font.PLAIN, 28)); // 水印文字字体 + config.put("color",Color.gray); // 水印文字颜色 + config.put("xMove",80); // 水印之间的间隔 + config.put("yMove",80); // 水印之间的间隔 + config.put("degree",-40);// 旋转角度 + config.put("formatName","JPG"); + return config; + } + + + public static Map getPdfDefaultConfig(){ + Map config = new HashMap<>(); + try { + config.put("baseFont",BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED)); + } catch ( IOException|DocumentException e) { + throw new RuntimeException(e); + } + config.put("fillOpacity",0.3f);// 填充透明度 + config.put("strokeOpacity",0.4f);// 笔划不透明度 + config.put("fontSize",16);//字体大小 + config.put("interval",-15);// 水印间隔 + config.put("rotation",30);// 旋转角度 + return config; + } + + + /** + * 获取文本长度。汉字为1:1,英文和数字为2:1 + */ + private static int getTextLength(String text) { + int length = text.length(); + for (int i = 0; i < text.length(); i++) { + String s = String.valueOf(text.charAt(i)); + if (s.getBytes().length > 1) { + length++; + } + } + length = length % 2 == 0 ? length / 2 : length / 2 + 1; + return length; + } + + public static void pdfByText(InputStream inputStream, OutputStream outputStream, String waterMarkName,Map config) throws DocumentException, IOException { + PdfReader reader = new PdfReader(inputStream); + PdfStamper stamper = new PdfStamper(reader, outputStream); + try { + + BaseFont base = (BaseFont) config.getOrDefault("baseFont",pdfConfig.get("baseFont")); + + com.itextpdf.text.Rectangle pageRect; + PdfGState gs = new PdfGState(); + gs.setFillOpacity((Float) config.getOrDefault("fillOpacity",pdfConfig.get("fillOpacity"))); + gs.setStrokeOpacity((Float) config.getOrDefault("strokeOpacity",pdfConfig.get("strokeOpacity"))); + int total = reader.getNumberOfPages() + 1; + + JLabel label = new JLabel(); + FontMetrics metrics; + int textH; + int textW; + label.setText(waterMarkName); + metrics = label.getFontMetrics(label.getFont()); + textH = metrics.getHeight(); + textW = metrics.stringWidth(label.getText()); + + PdfContentByte under; + int interval = (int) config.getOrDefault("interval", pdfConfig.get("interval")); + int rotation = (int) config.getOrDefault("rotation", pdfConfig.get("rotation")); + int fontSize = (int) config.getOrDefault("fontSize", pdfConfig.get("fontSize")); + for (int i = 1; i < total; i++) { + pageRect = reader.getPageSizeWithRotation(i); + under = stamper.getOverContent(i); + under.saveState(); + under.setGState(gs); + under.beginText(); + under.setFontAndSize(base, fontSize); + + + for (int height = interval + textH; height < pageRect.getHeight(); height = height + textH * 3) { + for (int width = interval + textW; width < pageRect.getWidth() + textW; width = width + textW * 2) { + under.showTextAligned(Element.ALIGN_LEFT + , waterMarkName, width - textW, height - textH, rotation); + } + } + // 添加水印文字 + under.endText(); + } + + } finally { + stamper.close(); + reader.close(); + } + } + + + /** + * 给图片添加水印文字、可设置水印文字的旋转角度 + * @param logoText 水印文字 + * @param inputStream + * @param outputStream + */ + public static void ImageByText(String logoText, InputStream inputStream, OutputStream outputStream, Map config) throws IOException { + + // 源图片 + Image srcImg = ImageIO.read(inputStream); + + // 原图宽度 + int width = srcImg.getWidth(null); + + // 原图高度 + int height = srcImg.getHeight(null); + + BufferedImage buffImg = new BufferedImage(srcImg.getWidth(null), srcImg.getHeight(null), BufferedImage.TYPE_INT_RGB); + // 构建画笔对象 + Graphics2D g = buffImg.createGraphics(); + try { + + // 设置对线段的锯齿状边缘处理 + g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); + g.drawImage(srcImg.getScaledInstance(srcImg.getWidth(null), srcImg.getHeight(null), Image.SCALE_SMOOTH), 0, 0, null); + // 设置水印旋转 + Integer degree = (Integer) config.getOrDefault("degree", imageConfig.get("degree")); + if (null != degree) { + g.rotate(Math.toRadians(degree), (double) buffImg.getWidth() / 2, (double) buffImg.getHeight() / 2); + } + // 设置水印文字颜色 + g.setColor((Color) config.getOrDefault("color", imageConfig.get("color"))); + // 设置水印文字Font + g.setFont((Font) config.getOrDefault("font", imageConfig.get("font"))); + // 设置水印文字透明度 + g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, (Float) config.getOrDefault("alpha", imageConfig.get("alpha")))); + + int x = -width / 2; + int y; + + // 字体高度 + int markHeight = (int) config.getOrDefault("fontSize", imageConfig.get("fontSize")); + + // 字体长度 + int markWidth = markHeight * getTextLength(logoText); + + // 循环添加水印 + while (x < width * 1.5) { + y = -height / 2; + while (y < height * 1.5) { + g.drawString(logoText, x, y); + y += markHeight + (int) config.getOrDefault("yMove", imageConfig.get("yMove")); + } + x += markWidth + (int) config.getOrDefault("xMove", imageConfig.get("xMove")); + } + } finally { + // 释放资源 + g.dispose(); + } + + // 生成图片 + ImageIO.write(buffImg, (String) config.getOrDefault("formatName", imageConfig.get("formatName")), outputStream); + + } + +} diff --git a/src/test/java/com/supervision/demo/WordRenderTest.java b/src/test/java/com/supervision/demo/WordRenderTest.java index 8da54ae..396b961 100644 --- a/src/test/java/com/supervision/demo/WordRenderTest.java +++ b/src/test/java/com/supervision/demo/WordRenderTest.java @@ -12,7 +12,7 @@ import org.springframework.boot.test.context.SpringBootTest; import java.io.*; import java.util.HashMap; - +import java.io.IOException; @Slf4j @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) public class WordRenderTest { @@ -23,7 +23,7 @@ public class WordRenderTest { @Autowired private ModelService modelService; - public static void main(String[] args) throws FileNotFoundException { + public static void main1(String[] args) throws FileNotFoundException { HashMap data = new HashMap<>(); data.put("name", "张三"); @@ -42,6 +42,86 @@ public class WordRenderTest { } //裴金禄涉嫌合同诈骗案详情-v0.docx + public static void main(String[] args) { + + } + + /*ublic static void main(String[] args) { + + try { + //水印文字 + String str = "裴金禄"; + // 原图片的路径 + File inputImage = new File("F:\\tmp\\1\\赵耀文第一次\\赵耀文第一次-1.jpg"); + // 输出图片的路径 + File outputImage = new File("F:\\tmp\\1\\赵耀文第一次\\赵耀文第一次-水印.jpg"); + + // 构建一个image对象 + BufferedImage img = ImageIO.read(inputImage); + int width = img.getWidth(); + int height = img.getHeight(); + + // 计算字体大小 + int fontSize = (width + height) / 80; + + Graphics2D g = img.createGraphics(); + g.setFont(new Font("黑体", Font.PLAIN, fontSize)); + g.setColor(new Color(0, 0, 0, 30)); + + // 旋转角度 + g.rotate(-0.6); + + // 间隔 + int split = fontSize * 2; + // 文字占用的宽度 + int xWidth = getStrWidth(str, fontSize); + // x,y可以绘制的数量,多加一个补充空白 + int xCanNum = width / xWidth + 1; + int yCanNum = height / fontSize + 1; + for (int i = 1; i <= yCanNum; i++) { + int y = fontSize * i + split * i; + for (int j = 0; j < xCanNum; j++) { + int x = xWidth * j + split * j; + g.drawString(str, x, y - (fontSize + split) * j); + } + } + g.dispose(); + ImageIO.write(img, "png", outputImage); + + } catch (Exception e) { + e.printStackTrace(); + } + }*/ + + + + /** + * 获取字符串占用的宽度 + * + * @param str 字符串 + * @param fontSize 文字大小 + * @return 字符串占用的宽度 + */ + public static int getStrWidth(String str, int fontSize) { + char[] chars = str.toCharArray(); + int fontSize2 = fontSize / 2; + + int width = 0; + + for (char c : chars) { + int len = String.valueOf(c).getBytes().length; + // 汉字为3,其余1 + // 可能还有一些特殊字符占用2 等等,统统计为汉字· + if (len != 1) { + width += fontSize; + } else { + width += fontSize2; + } + } + return width; + } + + @Test public void test() throws FileNotFoundException { CaseScoreDetailDTO caseScoreDetailDTO = modelService.caseScoreDetail("1810902613967384577");