Spire.Doc for Java实现根据关键字位置加盖电子签章及转换PDF
Spire.Doc for Java 是一款专业的 Java Word 组件,开发人员使用它可以轻松地将 Word 文档创建、读取、编辑、转换和打印等功能集成到自己的 Java 应用程序中。作为一款完全独立的组件,Spire.Doc for Java 的运行环境无需安装 Microsoft Office。
Spire.Doc for Java 能执行多种 Word 文档处理任务,包括生成、读取、转换和打印 Word 文档,插入图片,添加页眉和页脚,创建表格,添加表单域和邮件合并域,添加书签,添加文本和图片水印,设置背景颜色和背景图片,添加脚注和尾注,添加超链接,加密和解密 Word 文档,添加批注,添加形状等。
官方文档:https://www.e-iceblue.cn/content/spiredocforjava.html
实现代码:
1.maven依赖:
<!-- 电子签章实现 <!– 免费版 .free 只支持前三页转化 –>--> <!-- https://mvnrepository.com/artifact/e-iceblue/spire.doc.free --> <dependency> <groupId>e-iceblue</groupId> <artifactId>spire.doc.free</artifactId> <version>5.3.1</version> </dependency> <!-- 图片处理 如: 图片背景透明化 --> <dependency> <groupId>net.coobird</groupId> <artifactId>thumbnailator</artifactId> <version>0.4.8</version> </dependency> <repositories> epository> <id>com.e-iceblue</id> <url>http://repo.e-iceblue.cn/repository/maven-public/</url> </repository> </repositories>
2.工具类
SignUtil
public class SignUtil { /** * 创建带电子签章的文档 * * @param oldWordPath 无签章文件地址 "D:\\sign\\origin.docx" * @param signPath 电子印章图片地址 "D:\\sign\\sign.png" * @param pdfPath WORD转PDF存放位置 "D:\\sign\\3.pdf" * @param folderName 生成目标word文件夹名称 "D:\\sign\\" * @param targetFileName 生成目标word文件名称 "target.docx" * @param keyWord word文档内容关键字决定盖章位置 比如 "盖章" */ public static void createSign(String oldWordPath, String signPath, String pdfPath, String folderName, String targetFileName,String keyWord) { // 目标文件地址 String wordOldUrl = oldWordPath; // 添加电子印章后文件存放地址 String wordNewUrl = folderName + targetFileName; // WORD转PDF存放位置 String pdfNewUrl = pdfPath; // 电子印章图片地址 String stampImgUrl = signPath; // 索引,默认就填-1即可 Integer keyWordIndex = -1; // 电子印章水平位置 float horizontal = 270; // 电子印章垂直位置 float vertical = -60f; // 电子印章宽度 float stampWidth = 140; // 电子印章高度 float stampHeight = 120; // 书签名 String bookmarkName = "ZWSTTCJKBH"; // 书签位置文本替换新内容 String newBookmarkText = "公开"; AddStampUtils addStampUtils = new AddStampUtils(); // 获取关键字位置并加盖印章并替换书签名位置文本内容 addStampUtils.addKeyWordStamp(wordOldUrl, wordNewUrl, stampImgUrl, keyWord, keyWordIndex, horizontal, vertical, stampWidth, stampHeight, bookmarkName, newBookmarkText); // 转换为流 字节数组 byte[] bytesByFile = addStampUtils.getBytesByFile(wordNewUrl); // 流转换为文件 addStampUtils.byte2File(bytesByFile, folderName, targetFileName); // 将新word转化为pdf文件 addStampUtils.wordToPdf(wordNewUrl, pdfNewUrl); } }
AddStampUtils
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; import com.legendenergy.common.utils.StringUtils; import com.spire.doc.*; import com.spire.doc.documents.*; import com.spire.doc.fields.DocPicture; import com.spire.doc.fields.TextRange; import lombok.extern.slf4j.Slf4j; import java.io.*; /** * @Description: Word文件操作工具类 */ @Slf4j public class AddStampUtils { /** * 1、自定义位置添加电子印章 * 2、替换书签名位置文本内容 bookmarkName传参为null,则不进行书签替换操作 * * @param wordOldUrl word文件路径 * @param wordNewUrl 新word文件路径 * @param stampImgUrl 电子印章图片路径 * @param horizontal 电子印章水平位置 (当前文件推荐260f) * @param vertical 电子印章垂直位置 (当前推荐455f) * @param stampWidth 电子印章宽度(推荐120) * @param stampHeight 电子印章高度(推荐120) * @param bookmarkName 书签名,通过名称寻找书签文本所在位置 * @param newBookmarkText 替换的文本新内容 */ public void addStamp( String wordOldUrl, String wordNewUrl, String stampImgUrl, Float horizontal, Float vertical, Float stampWidth, Float stampHeight, String bookmarkName, String newBookmarkText ) { // 加载文档 Document document = new Document(); document.loadFromFile(wordOldUrl); // 获取指定段落 Section section = document.getSections().get(0); // 获取段落总数 int count = section.getParagraphs().getCount(); log.info("获取文档内容段落总数{}", count); Paragraph paragraph = section.getParagraphs().get(0); // 判断是否需要替换书签位置文本内容 if (StringUtils.isNotEmpty(bookmarkName)) { replaceBookmarkContent(document, bookmarkName, newBookmarkText); } // 添加电子印章 DocPicture docPicture = paragraph.appendPicture(stampImgUrl); // 指定电子章位置 // 水平位置 docPicture.setHorizontalPosition(horizontal); // 垂直位置 docPicture.setVerticalPosition(vertical); // 设置电子章大小 docPicture.setWidth(stampWidth); docPicture.setHeight(stampHeight); // 设置图片位于文字顶层 docPicture.setTextWrappingStyle(TextWrappingStyle.In_Front_Of_Text); // 保存添加电子章的Word文档 document.saveToFile(wordNewUrl); document.dispose(); log.info("文档添加电子印章结束,新WORD文档地址:{}", wordNewUrl); } /** * 1、根据关键词位置添加电子印章 * 2、替换书签名位置文本内容 bookmarkName传参为null,则不进行书签替换操作 * * @param wordOldUrl word文件路径 * @param wordNewUrl 新word文件路径 * @param stampImgUrl 电子印章图片路径 * @param keyWord 关键字 (自定义) * @param keyWordIndex 关键字索引 (-1) * @param horizontal 电子印章水平位置 (260f) * @param vertical 电子印章垂直位置 (-55f) * @param stampWidth 电子印章宽度 (推荐120) * @param stampHeight 电子印章高度(推荐120) * @param bookmarkName 书签名,通过名称寻找书签文本所在位置 * @param newBookmarkText 替换的文本新内容 */ public void addKeyWordStamp( String wordOldUrl, String wordNewUrl, String stampImgUrl, String keyWord, Integer keyWordIndex, Float horizontal, Float vertical, Float stampWidth, Float stampHeight, String bookmarkName, String newBookmarkText ) { // 加载文档 Document document = new Document(); document.loadFromFile(wordOldUrl); // 判断是否需要替换书签位置文本内容 if (StringUtils.isNotEmpty(bookmarkName)) { replaceBookmarkContent(document, bookmarkName, newBookmarkText); } // 获取关键字位置 TextSelection[] textSelections = document.findAllString(keyWord, false, false); if (ObjectUtils.isNotEmpty(textSelections)) { Paragraph paragraph = textSelections[keyWordIndex > -1 ? 0 : textSelections.length - 1].getAsOneRange().getOwnerParagraph(); // 添加电子印章 DocPicture docPicture = paragraph.appendPicture(stampImgUrl); // 设置图片位于文字顶层 docPicture.setTextWrappingStyle(TextWrappingStyle.In_Front_Of_Text); // 指定电子章位置 // 水平位置 docPicture.setHorizontalPosition(horizontal); // 垂直位置 docPicture.setVerticalPosition(vertical); // 设置电子章大小 docPicture.setWidth(stampWidth); docPicture.setHeight(stampHeight); } // 保存添加电子章的Word文档 document.saveToFile(wordNewUrl); document.dispose(); log.info("文档添加电子印章结束,新WORD文档地址:{}", wordNewUrl); } /** * 替换书签名位置文本内容 * * @param document word文档对象 * @param bookmarkName 书签名 * @param newBookmarkText 新文本内容 */ public void replaceBookmarkContent(Document document, String bookmarkName, String newBookmarkText) { //定位到指定书签位置 BookmarksNavigator bookmarksNavigator = new BookmarksNavigator(document); bookmarksNavigator.moveToBookmark(bookmarkName); //用文本内容替换原有书签位置的文本,新替换的内容与原文格式一致 bookmarksNavigator.replaceBookmarkContent(newBookmarkText, true); } /** * 替换书签名位置文本内容为图片 * * @param document word文档对象 * @param bookmarkName 书签名 * @param newImgUrl 图片地址 */ public void replaceBookmarkContentToImg(Document document, String bookmarkName, String newImgUrl) { //定位到指定书签位置 BookmarksNavigator bookmarksNavigator = new BookmarksNavigator(document); bookmarksNavigator.moveToBookmark(bookmarkName); //添加图片,替换原有书签内容 Paragraph para = new Paragraph(document); para.appendPicture(newImgUrl); TextBodyPart bodyPart = new TextBodyPart(document); bodyPart.getBodyItems().add(para); bookmarksNavigator.replaceBookmarkContent(bodyPart); } /** * 替换书签名位置文本内容为表格 * * @param document word文档对象 * @param bookmarkName 书签名 */ public void replaceBookmarkContentToTable(Document document, String bookmarkName) { //声明数组内容 String[][] data = { new String[]{"分类", "等级", "编号"}, new String[]{"A", "一级", "01A"}, new String[]{"B", "二级", "02B"}, new String[]{"C", "三级", "03C"}, }; //创建表格 Table table = new Table(document, true); table.resetCells(4, 3); for (int i = 0; i < data.length; i++) { TableRow dataRow = table.getRows().get(i); for (int j = 0; j < data[i].length; j++) { TextRange range = dataRow.getCells().get(j).addParagraph().appendText(data[i][j]); range.getOwnerParagraph().getFormat().setHorizontalAlignment(HorizontalAlignment.Center); range.getCharacterFormat().setFontName("楷体"); dataRow.getRowFormat().setHorizontalAlignment(RowAlignment.Center); dataRow.getCells().get(j).getCellFormat().setVerticalAlignment(VerticalAlignment.Middle); } } //创建TextBodyPart对象 TextBodyPart bodyPart = new TextBodyPart(document); bodyPart.getBodyItems().add(table); //定位到指定书签位置 BookmarksNavigator bookmarkNavigator = new BookmarksNavigator(document); bookmarkNavigator.moveToBookmark(bookmarkName); //使用表格替换原书签的内容 bookmarkNavigator.replaceBookmarkContent(bodyPart); } /** * 文件转流 * * @param wordNewUrl * @return */ public byte[] getBytesByFile(String wordNewUrl) { try { // byte[] bytes = Files.readAllBytes(Paths.get(wordNewUrl)); File file = new File(wordNewUrl); FileInputStream fis = new FileInputStream(file); ByteArrayOutputStream bos = new ByteArrayOutputStream(); byte[] b = new byte[1024]; int len = -1; while ((len = fis.read(b)) != -1) { bos.write(b, 0, len); } fis.close(); bos.close(); byte[] bytes = bos.toByteArray(); System.out.println("successful..."); return bytes; } catch (Exception e) { e.printStackTrace(); } return null; } /** * 流转文件 * * @param buf 流字节数组 * @param filePath 新文件路径 * @param fileName 新文件名称 */ public void byte2File(byte[] buf, String filePath, String fileName) { BufferedOutputStream bos = null; FileOutputStream fos = null; File file = null; try { File dir = new File(filePath); if (!dir.exists() && dir.isDirectory()) { dir.mkdirs(); } file = new File(filePath + File.separator + fileName); fos = new FileOutputStream(file); bos = new BufferedOutputStream(fos); bos.write(buf); } catch (Exception e) { e.printStackTrace(); } finally { if (bos != null) { try { bos.close(); } catch (IOException e) { e.printStackTrace(); } } if (fos != null) { try { fos.close(); } catch (IOException e) { e.printStackTrace(); } } } } /** * word转PDF * * @param wordNewUrl word文件路径 * @param pdfNewUrl 存储新PDF文件路径 */ public void wordToPdf(String wordNewUrl, String pdfNewUrl) { // 将新Word文档转换为PDF文件 Document document = new Document(); document.loadFromFile(wordNewUrl); document.saveToFile(pdfNewUrl, FileFormat.PDF); document.dispose(); log.info("文档转换结束,新PDF文档地址:{}", pdfNewUrl); } }
import net.coobird.thumbnailator.Thumbnails; import javax.imageio.ImageIO; import javax.swing.*; import java.awt.*; import java.awt.image.BufferedImage; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; public class ImageUtils { /** * 创建缩略图 * @param sourcePath * @param outputPath */ public static void createThumbnail(String sourcePath, String outputPath, int x1, int y1, int w, int h) throws IOException { File inputfile = new File(sourcePath); File outfile = new File(outputPath); Thumbnails.of(inputfile).sourceRegion(x1, y1, w, h).size(w, h).outputFormat("png").toFile(outfile); } /** * 将图章图片透明化 * * @param sourcePath "D:\\sign\\22.png" * @param outputPath "D:\\sign\\33.png" */ public static void transparentImage(String sourcePath, String outputPath) { InputStream is = null; try { File file = new File(sourcePath); is = new FileInputStream(file); // 如果是MultipartFile类型,那么自身也有转换成流的方法:is = file.getInputStream(); BufferedImage bi = ImageIO.read(is); Image image = (Image) bi; ImageIcon imageIcon = new ImageIcon(image); BufferedImage bufferedImage = new BufferedImage(imageIcon.getIconWidth(), imageIcon.getIconHeight(), BufferedImage.TYPE_4BYTE_ABGR); Graphics2D g2D = (Graphics2D) bufferedImage.getGraphics(); g2D.drawImage(imageIcon.getImage(), 0, 0, imageIcon.getImageObserver()); int alpha = 0; for (int j1 = bufferedImage.getMinY(); j1 < bufferedImage.getHeight(); j1++) { for (int j2 = bufferedImage.getMinX(); j2 < bufferedImage.getWidth(); j2++) { int rgb = bufferedImage.getRGB(j2, j1); int R = (rgb & 0xff0000) >> 16; int G = (rgb & 0xff00) >> 8; int B = (rgb & 0xff); if (((255 - R) < 30) && ((255 - G) < 30) && ((255 - B) < 30)) { rgb = ((alpha + 1) << 24) | (rgb & 0x00ffffff); } bufferedImage.setRGB(j2, j1, rgb); } } g2D.drawImage(bufferedImage, 0, 0, imageIcon.getImageObserver()); ImageIO.write(bufferedImage, "png", new File(outputPath));// 直接输出文件 } catch (Exception e) { e.printStackTrace(); } finally { if (is != null) { try { is.close(); } catch (Exception e) { } } } } }
3.测试
yml文件
#文件下载路径 file: path: signPath: D:/sign
service实现类
@Value("${file.path.signPath}") private String signPath; //将签章图片透明化 ImageUtils.transparentImage(signPath + "/signOld.png", signPath + "/signNew.png"); //生成带签章的文档 SignUtil.createSign(signPath + "/合伙人协议.docx", signPath + "/signNew.png", signPath + "/南通xx合伙人协议.pdf", signPath + "/", "最终合伙人协议.docx", "乙方");
4:效果
5、注意事项
将word转化为PDF时,打开pdf,发现只有前三页有效 ,因为免费spire依赖只能转化前三页
now ,fight for future