Commit daf4f3d2 authored by fangxinjiang's avatar fangxinjiang

Merge remote-tracking branch 'origin/MVP1.7.11' into MVP1.7.11

parents 02d9a15b a537a4b4
...@@ -1059,7 +1059,6 @@ public class IcbcTransactionFlowIssueServiceImpl extends ServiceImpl<EkpSocialIn ...@@ -1059,7 +1059,6 @@ public class IcbcTransactionFlowIssueServiceImpl extends ServiceImpl<EkpSocialIn
// 私钥路径(用于身份验证) // 私钥路径(用于身份验证)
//E:\IdeaProjects\yifu_mvp\yifu-ekp\yifu-ekp-biz\src\main\resources\icbc\icbc //E:\IdeaProjects\yifu_mvp\yifu-ekp\yifu-ekp-biz\src\main\resources\icbc\icbc
String privateKeyPath = ""; String privateKeyPath = "";
// URL url = getClass().getClassLoader().getResource("icbc");
InputStream inputStream = getClass().getClassLoader().getResourceAsStream("icbc"); InputStream inputStream = getClass().getClassLoader().getResourceAsStream("icbc");
if (inputStream == null) { if (inputStream == null) {
throw new FileNotFoundException("资源未找到"); throw new FileNotFoundException("资源未找到");
...@@ -1076,7 +1075,6 @@ public class IcbcTransactionFlowIssueServiceImpl extends ServiceImpl<EkpSocialIn ...@@ -1076,7 +1075,6 @@ public class IcbcTransactionFlowIssueServiceImpl extends ServiceImpl<EkpSocialIn
} }
} }
privateKeyPath = tempFile.getAbsolutePath(); privateKeyPath = tempFile.getAbsolutePath();
// privateKeyPath = url.getPath();
// 远程目录路径 // 远程目录路径
log.info("秘钥文件目录: " + privateKeyPath); log.info("秘钥文件目录: " + privateKeyPath);
...@@ -1141,14 +1139,9 @@ public class IcbcTransactionFlowIssueServiceImpl extends ServiceImpl<EkpSocialIn ...@@ -1141,14 +1139,9 @@ public class IcbcTransactionFlowIssueServiceImpl extends ServiceImpl<EkpSocialIn
} }
String tempDir = System.getProperty("java.io.tmpdir") + "sftp_processing/" + System.currentTimeMillis() + "/"; String tempDir = System.getProperty("java.io.tmpdir") + "sftp_processing/" + System.currentTimeMillis() + "/";
File dir = new File(tempDir); File dir = new File(tempDir);
if (!dir.exists()) { if (!dir.exists() && !dir.mkdirs()) {
if (!dir.mkdirs()) { throw new IOException("Failed to create directory: " + tempDir);
throw new IOException("Failed to create directory: " + tempDir);
}
} }
// 3. 创建临时目录 System.getProperty("user.dir") + "/yifu-ekp/yifu-ekp-biz/src/main/resources/tem/sftp_processing/" + System.currentTimeMillis() + "/";
// String tempDir = privateKeyPath + "/temp/sftp_processing/" + System.currentTimeMillis() + "/";
// String tempDir = System.getProperty("user.dir") + "/yifu-ekp/yifu-ekp-biz/src/main/resources/temp/sftp_processing/" + System.currentTimeMillis() + "/";
log.info("临时目录: " + tempDir); log.info("临时目录: " + tempDir);
// 4. 下载并解压压缩包 // 4. 下载并解压压缩包
......
...@@ -2,6 +2,7 @@ package com.yifu.cloud.plus.v1.yifu.social.vo; ...@@ -2,6 +2,7 @@ package com.yifu.cloud.plus.v1.yifu.social.vo;
import com.alibaba.excel.annotation.ExcelProperty; import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.HeadFontStyle; import com.alibaba.excel.annotation.write.style.HeadFontStyle;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.yifu.cloud.plus.v1.yifu.common.core.constant.ExcelAttribute; import com.yifu.cloud.plus.v1.yifu.common.core.constant.ExcelAttribute;
import com.yifu.cloud.plus.v1.yifu.common.core.util.LocalDateTimeUtils; import com.yifu.cloud.plus.v1.yifu.common.core.util.LocalDateTimeUtils;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
...@@ -559,6 +560,7 @@ public class TPreDispatchExportVo implements Serializable { ...@@ -559,6 +560,7 @@ public class TPreDispatchExportVo implements Serializable {
/** /**
* 创建时间 * 创建时间
*/ */
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern="yyyy-MM-dd HH:mm:ss")
@HeadFontStyle(fontHeightInPoints = 11) @HeadFontStyle(fontHeightInPoints = 11)
@ExcelProperty(value ="创建时间") @ExcelProperty(value ="创建时间")
@ExcelAttribute(name = "创建时间", needExport = true, isDate = true, dateFormatExport = LocalDateTimeUtils.DATE_TIME_PATTERN) @ExcelAttribute(name = "创建时间", needExport = true, isDate = true, dateFormatExport = LocalDateTimeUtils.DATE_TIME_PATTERN)
......
...@@ -107,18 +107,15 @@ ...@@ -107,18 +107,15 @@
<type>jar</type> <type>jar</type>
</dependency> </dependency>
<!-- word转pdf -->
<dependency> <dependency>
<groupId>org.jodconverter</groupId> <groupId>com.deepoove</groupId>
<artifactId>jodconverter-local</artifactId> <artifactId>poi-tl</artifactId>
<version>4.4.0</version> <version>1.8.0</version>
</dependency> </dependency>
<!-- pdf转图片 -->
<dependency> <dependency>
<groupId>org.apache.pdfbox</groupId> <groupId>com.luhuiguo</groupId>
<artifactId>pdfbox</artifactId> <artifactId>aspose-words</artifactId>
<version>2.0.27</version> <version>23.1</version>
</dependency> </dependency>
</dependencies> </dependencies>
......
...@@ -27,8 +27,6 @@ import com.yifu.cloud.plus.v1.yifu.social.config.SocialFriendConfig; ...@@ -27,8 +27,6 @@ import com.yifu.cloud.plus.v1.yifu.social.config.SocialFriendConfig;
import com.yifu.cloud.plus.v1.yifu.social.entity.TSocialFriendBackLog; import com.yifu.cloud.plus.v1.yifu.social.entity.TSocialFriendBackLog;
import com.yifu.cloud.plus.v1.yifu.social.mapper.TAttaInfoMapper; import com.yifu.cloud.plus.v1.yifu.social.mapper.TAttaInfoMapper;
import com.yifu.cloud.plus.v1.yifu.social.util.WordToImageUtil; import com.yifu.cloud.plus.v1.yifu.social.util.WordToImageUtil;
import com.yifu.cloud.plus.v1.yifu.social.util.WordToImageWithSeal;
import com.yifu.cloud.plus.v1.yifu.social.util.WordUtil;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
...@@ -74,6 +72,9 @@ public class TSocialFriendWordController { ...@@ -74,6 +72,9 @@ public class TSocialFriendWordController {
@Autowired @Autowired
private OSSUtil ossUtil; private OSSUtil ossUtil;
@Autowired
private WordToImageUtil wordToImageUtil;
@Autowired @Autowired
private TAttaInfoMapper attaInfoMapper; private TAttaInfoMapper attaInfoMapper;
...@@ -111,38 +112,11 @@ public class TSocialFriendWordController { ...@@ -111,38 +112,11 @@ public class TSocialFriendWordController {
backLog.setSocialId("test"); backLog.setSocialId("test");
backLog.setType(CommonConstants.EIGHT_INT); backLog.setType(CommonConstants.EIGHT_INT);
backLog.setCreateTime(LocalDateTime.now()); backLog.setCreateTime(LocalDateTime.now());
String friendUrl = WordToImageUtil.replaceTextInWord(templateUrl.openStream() String friendUrl = wordToImageUtil.replaceTextInWord(templateUrl.openStream()
, replacements, imageStream, restTemplate, socialFriendConfig, backLog); , replacements, imageStream, restTemplate, socialFriendConfig, backLog);
return R.ok(friendUrl); return R.ok(friendUrl);
} }
} }
return R.ok(); return R.ok();
} }
public R<String> replaceText(String inputPath, String outputPath, String outputImagePath) throws Exception {
String src = "1735185038602皖信.png";
URL url = ossUtil.getObjectUrl(null, src);
if (Common.isEmpty(url)) {
throw new RuntimeException("获取印章图片失败");
}
try (InputStream imageStream = url.openStream()) {
// 准备替换参数
Map<String, String> replacements = new HashMap<>();
replacements.put("empName", "张三丰");
replacements.put("empSex", "女");
replacements.put("empAge", "33");
replacements.put("idCard", "340826199012121212");
replacements.put("startDate", "2023年11月28日");
replacements.put("leaveReason", "个人原因");
replacements.put("leaveDate", "2025年01月20日");
replacements.put("nowDate", DateUtil.formatDatePatten(new Date(), DateUtil.CHINA_PATTEN_YMD));
// 执行替换 + 插入印章
WordUtil.replaceTextInWord(inputPath, outputPath, replacements);
WordToImageWithSeal.convertAndAddSeal(outputPath, imageStream, outputImagePath);
}
return R.ok();
}
} }
...@@ -24,7 +24,6 @@ import com.alibaba.excel.write.style.row.SimpleRowHeightStyleStrategy; ...@@ -24,7 +24,6 @@ import com.alibaba.excel.write.style.row.SimpleRowHeightStyleStrategy;
import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.yifu.cloud.plus.v1.yifu.archives.entity.TEmployeeContractInfo;
import com.yifu.cloud.plus.v1.yifu.archives.util.IdCardUtil; import com.yifu.cloud.plus.v1.yifu.archives.util.IdCardUtil;
import com.yifu.cloud.plus.v1.yifu.common.core.constant.CommonConstants; import com.yifu.cloud.plus.v1.yifu.common.core.constant.CommonConstants;
import com.yifu.cloud.plus.v1.yifu.common.core.util.Common; import com.yifu.cloud.plus.v1.yifu.common.core.util.Common;
...@@ -84,6 +83,8 @@ public class TSocialFriendPushServiceImpl extends ServiceImpl<TSocialFriendMappe ...@@ -84,6 +83,8 @@ public class TSocialFriendPushServiceImpl extends ServiceImpl<TSocialFriendMappe
@Autowired @Autowired
private ExcelToImage excelToImage; private ExcelToImage excelToImage;
@Autowired @Autowired
private WordToImageUtil wordToImageUtil;
@Autowired
private OSSUtil ossUtil; private OSSUtil ossUtil;
@Autowired @Autowired
...@@ -352,7 +353,7 @@ public class TSocialFriendPushServiceImpl extends ServiceImpl<TSocialFriendMappe ...@@ -352,7 +353,7 @@ public class TSocialFriendPushServiceImpl extends ServiceImpl<TSocialFriendMappe
backLog.setSocialId(vo.getEmpIdcard()); backLog.setSocialId(vo.getEmpIdcard());
backLog.setType(type); backLog.setType(type);
backLog.setCreateTime(LocalDateTime.now()); backLog.setCreateTime(LocalDateTime.now());
String friendUrl = WordToImageUtil.replaceTextInWord(templateUrl.openStream() String friendUrl = wordToImageUtil.replaceTextInWord(templateUrl.openStream()
, replacements, imageStream, restTemplate, socialFriendConfig, backLog); , replacements, imageStream, restTemplate, socialFriendConfig, backLog);
// System.out.println("看看URL111:"+friendUrl) // System.out.println("看看URL111:"+friendUrl)
tSocialFriendBackLogService.save(backLog); tSocialFriendBackLogService.save(backLog);
......
...@@ -19,7 +19,6 @@ import java.io.IOException; ...@@ -19,7 +19,6 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.net.URL; import java.net.URL;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Base64; import java.util.Base64;
/** /**
...@@ -63,7 +62,8 @@ public class ExcelToImage { ...@@ -63,7 +62,8 @@ public class ExcelToImage {
if (file.exists()){ if (file.exists()){
// file 压缩到1M以内 // file 压缩到1M以内
backLog.setLogInfo("压缩大小前"); backLog.setLogInfo("压缩大小前");
file = compressImage(projectRoot, toImag, 1024 * 1024); file = compressImage(file, projectRoot);
backLog.setLogInfo("压缩大小后");
String key = System.currentTimeMillis() + file.getName(); String key = System.currentTimeMillis() + file.getName();
byte[] fileContent = Files.readAllBytes(file.toPath()); byte[] fileContent = Files.readAllBytes(file.toPath());
String base64String = Base64.getEncoder().encodeToString(fileContent); String base64String = Base64.getEncoder().encodeToString(fileContent);
...@@ -75,6 +75,7 @@ public class ExcelToImage { ...@@ -75,6 +75,7 @@ public class ExcelToImage {
return R.ok(url); return R.ok(url);
} }
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace();
return R.failed(CommonConstants.RESULT_DATA_FAIL+toImagConvertError+e.getMessage()); return R.failed(CommonConstants.RESULT_DATA_FAIL+toImagConvertError+e.getMessage());
} finally { } finally {
if (file.exists()){ if (file.exists()){
...@@ -91,11 +92,11 @@ public class ExcelToImage { ...@@ -91,11 +92,11 @@ public class ExcelToImage {
return R.failed(CommonConstants.RESULT_DATA_FAIL); return R.failed(CommonConstants.RESULT_DATA_FAIL);
} }
//压缩文件到指定大小 //压缩文件到指定大小
private File compressImage(String projectRoot, String toImag, int maxSize) throws IOException { private File compressImage(File originalFile, String projectRoot) throws IOException {
File originalFile = Paths.get(projectRoot, toImag).toFile();
BufferedImage image = ImageIO.read(originalFile); BufferedImage image = ImageIO.read(originalFile);
int quality = 100; // 从100%开始 int quality = 100; // 从100%开始
File compressedFile = new File(projectRoot, TO_IMAGE_TEMP); File compressedFile = new File(projectRoot, TO_IMAGE_TEMP);
int maxSize = 1024 * 1024;
while (originalFile.length() > maxSize && quality > 10) { while (originalFile.length() > maxSize && quality > 10) {
quality -= 5; quality -= 5;
ImageIO.write(image, "png", compressedFile); ImageIO.write(image, "png", compressedFile);
...@@ -108,6 +109,7 @@ public class ExcelToImage { ...@@ -108,6 +109,7 @@ public class ExcelToImage {
} }
return originalFile; return originalFile;
} }
public R<URL> excelToImg(InputStream inputStream ,OSSUtil ossUtil){ public R<URL> excelToImg(InputStream inputStream ,OSSUtil ossUtil){
if (null == inputStream || null == ossUtil){ if (null == inputStream || null == ossUtil){
return R.failed(CommonConstants.RESULT_DATA_FAIL+toImagParamError); return R.failed(CommonConstants.RESULT_DATA_FAIL+toImagParamError);
......
package com.yifu.cloud.plus.v1.yifu.social.util; package com.yifu.cloud.plus.v1.yifu.social.util;
import com.aspose.words.Document;
import com.aspose.words.SaveFormat;
import com.yifu.cloud.plus.v1.yifu.common.core.constant.CommonConstants; import com.yifu.cloud.plus.v1.yifu.common.core.constant.CommonConstants;
import com.yifu.cloud.plus.v1.yifu.common.core.util.Common; import com.yifu.cloud.plus.v1.yifu.common.core.util.Common;
import com.yifu.cloud.plus.v1.yifu.social.config.SocialFriendConfig; import com.yifu.cloud.plus.v1.yifu.social.config.SocialFriendConfig;
import com.yifu.cloud.plus.v1.yifu.social.entity.TSocialFriendBackLog; import com.yifu.cloud.plus.v1.yifu.social.entity.TSocialFriendBackLog;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.ImageType;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.apache.poi.xwpf.usermodel.*; import org.apache.poi.xwpf.usermodel.*;
import org.jodconverter.core.office.OfficeException; import org.springframework.stereotype.Component;
import org.jodconverter.core.office.OfficeManager;
import org.jodconverter.local.LocalConverter;
import org.jodconverter.local.office.LocalOfficeManager;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
import java.awt.*; import java.awt.*;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.io.File; import java.io.*;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.DirectoryNotEmptyException;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Base64; import java.util.Base64;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
/** /**
...@@ -34,12 +23,13 @@ import java.util.Map; ...@@ -34,12 +23,13 @@ import java.util.Map;
* @description word工具类 * @description word工具类
* @date 2025-5-26 16:03:05 * @date 2025-5-26 16:03:05
*/ */
@Component
public class WordToImageUtil { public class WordToImageUtil {
private static final String PDF_TEMP ="\\test126666.docx"; private static final String PDF_TEMP ="\\test126666.docx";
private static final String IMAGE_TEMP ="\\document_with_seal.png"; private static final String IMAGE_TEMP ="\\document_with_seal.png";
private static final String TO_IMAGE_TEMP ="\\ToImgTemp.png"; private static final String TO_IMAGE_TEMP ="\\ToImgTemp.png";
public static String replaceTextInWord(InputStream templateFile, Map<String, String> replacements public String replaceTextInWord(InputStream templateFile, Map<String, String> replacements
, InputStream imageStream, RestTemplate restTemplate, SocialFriendConfig socialFriendConfig , InputStream imageStream, RestTemplate restTemplate, SocialFriendConfig socialFriendConfig
, TSocialFriendBackLog backLog) { , TSocialFriendBackLog backLog) {
String projectRoot = System.getProperty(CommonConstants.USER_DIR); String projectRoot = System.getProperty(CommonConstants.USER_DIR);
...@@ -82,16 +72,6 @@ public class WordToImageUtil { ...@@ -82,16 +72,6 @@ public class WordToImageUtil {
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} finally { } finally {
Path outputPath = Paths.get(outputFilePath);
if (Files.exists(outputPath)) {
try {
Files.delete(outputPath); // 如果文件不存在会抛异常,先判断是否存在
} catch (DirectoryNotEmptyException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
if (imageStream != null) { if (imageStream != null) {
try { try {
imageStream.close(); imageStream.close();
...@@ -103,41 +83,32 @@ public class WordToImageUtil { ...@@ -103,41 +83,32 @@ public class WordToImageUtil {
return "-"; return "-";
} }
// 在生产环境中,建议在整个应用生命周期中共享一个OfficeManager: public String convertAndAddSeal(String inputDocx, InputStream sealImagePath, String outputImagePath
public static OfficeManager OFFICE_MANAGER;
static {
OFFICE_MANAGER = LocalOfficeManager.builder()
.portNumbers(2003)
.build();
try {
OFFICE_MANAGER.start();
} catch (OfficeException e) {
e.printStackTrace();
}
}
public static String convertAndAddSeal(String inputDocx, InputStream sealImagePath, String outputImagePath
, String projectRoot, RestTemplate restTemplate, SocialFriendConfig socialFriendConfig , String projectRoot, RestTemplate restTemplate, SocialFriendConfig socialFriendConfig
, TSocialFriendBackLog backLog) throws IOException, OfficeException { , TSocialFriendBackLog backLog) throws Exception {
File pdfFile = null; File pdfFile = null;
Document doc = null;
File tempImgFile = null;
File imgFile = null; File imgFile = null;
try { try {
// Step 1: Word 转为 PDF(中间格式)
pdfFile = new File(inputDocx.replace(".docx", ".pdf"));
Map<String, Object> pdfProps = new HashMap<>();
pdfProps.put("FilterName", "writer_pdf_Export");
pdfProps.put("SelectPdfVersion", 1); // PDF/A-1
LocalConverter.builder()
.officeManager(OFFICE_MANAGER)
.storeProperties(pdfProps)
.build()
.convert(new File(inputDocx))
.to(pdfFile)
.execute();
// Step 2: PDF 转为 PNG 图片(可使用 Apache PDFBox 或 ImageMagick 转换)
BufferedImage pageImage = convertPdfToImage(pdfFile.getAbsolutePath());
pdfFile = new File(inputDocx);
String filename = pdfFile.getName();
// 打开生成的 Word 文件
doc = new Document(new FileInputStream(pdfFile));
String pathPre = filename.substring(0, filename.lastIndexOf("."));
// 逐页将 Word 文件保存为图片(PNG格式)
String path = pathPre + ".png";
if (doc.getPageCount() > 0) {
Document extractedPage = doc.extractPages(0,1);
// 拼接上文件名 test1.png
// 将 Word 文件保存为图片PNG格式
extractedPage.save(path, SaveFormat.PNG);
}
tempImgFile = new File(path);
BufferedImage pageImage = ImageIO.read(tempImgFile);
// Step 3: 加盖公章 // Step 3: 加盖公章
BufferedImage sealedImage = addSealToImage(pageImage, sealImagePath); BufferedImage sealedImage = addSealToImage(pageImage, sealImagePath);
...@@ -156,18 +127,27 @@ public class WordToImageUtil { ...@@ -156,18 +127,27 @@ public class WordToImageUtil {
} }
return url; return url;
} }
} catch (Exception e) {
e.printStackTrace();
} finally { } finally {
if (tempImgFile != null) {
tempImgFile.delete();
}
if (doc != null) {
doc.cleanup();
}
if (pdfFile != null) { if (pdfFile != null) {
pdfFile.delete(); pdfFile.delete();
} }
if (imgFile != null) { if (imgFile != null) {
imgFile.delete(); imgFile.delete();
} }
} }
return "---"; return "---";
} }
private static File compressImage(String projectRoot, File originalFile) throws IOException { private File compressImage(String projectRoot, File originalFile) throws IOException {
BufferedImage image = ImageIO.read(originalFile); BufferedImage image = ImageIO.read(originalFile);
int quality = 100; // 从100%开始 int quality = 100; // 从100%开始
File compressedFile = new File(projectRoot, TO_IMAGE_TEMP); File compressedFile = new File(projectRoot, TO_IMAGE_TEMP);
...@@ -185,30 +165,36 @@ public class WordToImageUtil { ...@@ -185,30 +165,36 @@ public class WordToImageUtil {
return originalFile; return originalFile;
} }
private static BufferedImage convertPdfToImage(String pdfPath) throws IOException {
try (PDDocument document = PDDocument.load(new File(pdfPath))) {
PDFRenderer pdfRenderer = new PDFRenderer(document);
// 渲染第一页为图像,分辨率为 300 DPI
return pdfRenderer.renderImageWithDPI(0, 300, ImageType.RGB);
}
}
private static BufferedImage addSealToImage(BufferedImage image, InputStream sealImagePath) throws IOException { private BufferedImage addSealToImage(BufferedImage image, InputStream sealImagePath) throws IOException {
BufferedImage seal = ImageIO.read(sealImagePath); BufferedImage seal = ImageIO.read(sealImagePath);
// 设置公章目标大小
int targetWidth = 200; // 宽度
int targetHeight = 200; // 高度
// 创建缩放后的公章图像
Image scaledSeal = seal.getScaledInstance(targetWidth, targetHeight, Image.SCALE_SMOOTH);
BufferedImage resizedSeal = new BufferedImage(targetWidth, targetHeight, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = resizedSeal.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.drawImage(scaledSeal, 0, 0, null);
g2d.dispose();
// 合成最终图像
BufferedImage combined = new BufferedImage( BufferedImage combined = new BufferedImage(
image.getWidth(), image.getWidth(),
image.getHeight(), image.getHeight(),
BufferedImage.TYPE_INT_ARGB); BufferedImage.TYPE_INT_ARGB);
Graphics2D g = combined.createGraphics(); Graphics2D g = combined.createGraphics();
g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g.drawImage(image, 0, 0, null); g.drawImage(image, 0, 0, null);
// 设置公章位置(右下角) // 设置公章位置(右下角)
int x = 1600; int x = 550;
int y = 1150; int y = 400;
g.drawImage(seal, x, y, null); g.drawImage(resizedSeal, x, y, null);
g.dispose(); g.dispose();
return combined; return combined;
......
package com.yifu.cloud.plus.v1.yifu.social.util;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.ImageType;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.jodconverter.core.office.OfficeException;
import org.jodconverter.core.office.OfficeManager;
import org.jodconverter.local.LocalConverter;
import org.jodconverter.local.office.LocalOfficeManager;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
/**
* @author hgw2
* @description word转图片
* @date 2025/5/15
*/
public class WordToImageWithSeal {
// 在生产环境中,建议在整个应用生命周期中共享一个OfficeManager:
public static OfficeManager OFFICE_MANAGER;
static {
OFFICE_MANAGER = LocalOfficeManager.builder()
.portNumbers(2002)
.build();
try {
OFFICE_MANAGER.start();
} catch (OfficeException e) {
e.printStackTrace();
}
}
public static void convertAndAddSeal(String inputDocx, InputStream sealImagePath, String outputImagePath) throws IOException, OfficeException {
// Step 1: Word 转为 PDF(中间格式)
File pdfFile = new File(inputDocx.replace(".docx", ".pdf"));
Map<String, Object> pdfProps = new HashMap<>();
pdfProps.put("FilterName", "writer_pdf_Export");
pdfProps.put("SelectPdfVersion", 1); // PDF/A-1
LocalConverter.builder()
.officeManager(OFFICE_MANAGER)
.storeProperties(pdfProps)
.build()
.convert(new File(inputDocx))
.to(pdfFile)
.execute();
// Step 2: PDF 转为 PNG 图片(可使用 Apache PDFBox 或 ImageMagick 转换)
BufferedImage pageImage = convertPdfToImage(pdfFile.getAbsolutePath());
// Step 3: 加盖公章
BufferedImage sealedImage = addSealToImage(pageImage, sealImagePath);
// Step 4: 输出图片
ImageIO.write(sealedImage, "png", new File(outputImagePath));
}
private static BufferedImage convertPdfToImage(String pdfPath) throws IOException {
try (PDDocument document = PDDocument.load(new File(pdfPath))) {
PDFRenderer pdfRenderer = new PDFRenderer(document);
// 渲染第一页为图像,分辨率为 300 DPI
return pdfRenderer.renderImageWithDPI(0, 300, ImageType.RGB);
}
}
private static BufferedImage addSealToImage(BufferedImage image, InputStream sealImagePath) throws IOException {
BufferedImage seal = ImageIO.read(sealImagePath);
BufferedImage combined = new BufferedImage(
image.getWidth(),
image.getHeight(),
BufferedImage.TYPE_INT_ARGB);
Graphics2D g = combined.createGraphics();
g.drawImage(image, 0, 0, null);
// 设置公章位置(右下角)
int x = 1600;
int y = 1150;
g.drawImage(seal, x, y, null);
g.dispose();
return combined;
}
}
package com.yifu.cloud.plus.v1.yifu.social.util;
import com.yifu.cloud.plus.v1.yifu.common.core.util.Common;
import org.apache.poi.xwpf.usermodel.*;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Map;
/**
* @author hgw2
* @description word工具类
* @date 2025/5/15
*/
public class WordUtil {
public static void replaceTextInWord(String filePath, String outputFilePath, Map<String, String> replacements
) throws IOException {
try (FileInputStream fis = new FileInputStream(filePath);
XWPFDocument document = new XWPFDocument(fis)) {
// 替换段落中的文本
for (XWPFParagraph paragraph : document.getParagraphs()) {
for (String key : replacements.keySet()) {
if (paragraph.getText().contains(key)) {
String newText = paragraph.getText().replace(key, replacements.get(key));
paragraph.getRuns().clear();
XWPFRun newRun = paragraph.createRun();
newRun.setText(newText);
}
}
}
String text;
// 替换表格中的文本
for (XWPFTable table : document.getTables()) {
for (XWPFTableRow row : table.getRows()) {
for (XWPFTableCell cell : row.getTableCells()) {
for (XWPFParagraph p : cell.getParagraphs()) {
for (XWPFRun run : p.getRuns()) {
text = run.getText(0);
if (Common.isNotNull(text) && replacements.get(text) != null) {
run.setText(replacements.get(text), 0);
}
}
}
}
}
}
// 保存输出文件
try (FileOutputStream fos = new FileOutputStream(outputFilePath)) {
document.write(fos);
}
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment