SpringBoot+POI實現(xiàn)給word添加水印功能
1、前言
有個需求:整一個給 Word 加水印的demo,于是我就網(wǎng)上找唄~
看到那個 Aspose
好像是收費的,然后就把目光轉向了 POI,看到各種形形色色的也不知道哪個能用。整了一會,自己拷貝出一個比較精簡的能用的 demo 了。
2、人狠話不多,上效果圖
我一般都是直接上圖的,先看效果圖(每一頁都有的):
水印的分布如果不理想,只能小伙伴們自行研究調整了~
3、人狠話不多,直接來代碼
3.1、我的代碼結構
3.2 、直接貼代碼了
3.2.1、pom 依賴
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.2.2</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.lyk</groupId> <artifactId>springboot-word-finger</artifactId> <version>0.0.1-SNAPSHOT</version> <name>springboot-word-finger</name> <description>springboot-word-finger</description> <properties> <java.version>17</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.jsoup</groupId> <artifactId>jsoup</artifactId> <version>1.11.2</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>4.1.0</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-scratchpad</artifactId> <version>4.1.0</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>4.1.0</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml-schemas</artifactId> <version>4.1.0</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
3.2.2、處理工具類
import com.microsoft.schemas.office.office.CTLock; import com.microsoft.schemas.vml.*; import org.apache.poi.openxml4j.exceptions.InvalidFormatException; import org.apache.poi.openxml4j.opc.OPCPackage; import org.apache.poi.wp.usermodel.HeaderFooterType; import org.apache.poi.xwpf.usermodel.XWPFDocument; import org.apache.poi.xwpf.usermodel.XWPFHeader; import org.openxmlformats.schemas.wordprocessingml.x2006.main.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.*; import java.util.stream.Stream; /** * @author: lyk * @description: Word 添加水印工具類 **/ public class WatermarkUtil { private static final Logger LOGGER = LoggerFactory.getLogger(WatermarkUtil.class); /** word字體 */ private static final String FONT_NAME = "宋體"; /** 字體大小 */ private static final String FONT_SIZE = "0.2pt"; /** 字體顏色 */ private static final String FONT_COLOR = "#d0d0d0"; /** 一個字平均長度,單位pt,用于:計算文本占用的長度(文本總個數(shù)*單字長度)*/ private static final Integer WIDTH_PER_WORD = 10; /** 與頂部的間距 */ private static Integer STYLE_TOP = 0; /** 文本旋轉角度 */ private static final String STYLE_ROTATION = "30"; /** * @param inPutPath * @param putPutPath * @param fingerText * @author: lyk * @description: 添加水印入口方法 * @date: 2024/1/25 23:42 **/ public static void waterMarkDocXDocument(String inPutPath, String putPutPath, String fingerText) { long beginTime = System.currentTimeMillis(); try ( OutputStream out = new FileOutputStream(putPutPath); InputStream in = new FileInputStream(inPutPath); OPCPackage srcPackage = OPCPackage.open(in); XWPFDocument doc = new XWPFDocument(srcPackage) ) { // 把整頁都打上水印 for (int lineIndex = -5; lineIndex < 20; lineIndex++) { STYLE_TOP = 100 * lineIndex; waterMarkDocXDocument(doc, fingerText); } // 輸出新文檔 doc.write(out); LOGGER.info("添加水印成功!,一共耗時" + (System.currentTimeMillis() - beginTime) + "毫秒"); } catch (IOException e) { throw new RuntimeException(e); } catch (InvalidFormatException e) { throw new RuntimeException(e); } } /** * 為文檔添加水印 * @param doc 需要被處理的docx文檔對象 * @param fingerText 需要添加的水印文字 */ public static void waterMarkDocXDocument(XWPFDocument doc, String fingerText) { // 水印文字之間使用8個空格分隔 fingerText = fingerText + repeatString(" ", 8); // 一行水印重復水印文字次數(shù) fingerText = repeatString(fingerText, 10); // 如果之前已經(jīng)創(chuàng)建過 DEFAULT 的Header,將會復用 XWPFHeader header = doc.createHeader(HeaderFooterType.DEFAULT); int size = header.getParagraphs().size(); if (size == 0) { header.createParagraph(); } CTP ctp = header.getParagraphArray(0).getCTP(); byte[] rsidr = doc.getDocument().getBody().getPArray(0).getRsidR(); byte[] rsidrDefault = doc.getDocument().getBody().getPArray(0).getRsidRDefault(); ctp.setRsidP(rsidr); ctp.setRsidRDefault(rsidrDefault); CTPPr ppr = ctp.addNewPPr(); ppr.addNewPStyle().setVal("Header"); // 開始加水印 CTR ctr = ctp.addNewR(); CTRPr ctrpr = ctr.addNewRPr(); ctrpr.addNewNoProof(); CTGroup group = CTGroup.Factory.newInstance(); CTShapetype shapeType = group.addNewShapetype(); CTTextPath shapeTypeTextPath = shapeType.addNewTextpath(); shapeTypeTextPath.setOn(STTrueFalse.T); shapeTypeTextPath.setFitshape(STTrueFalse.T); CTLock lock = shapeType.addNewLock(); lock.setExt(STExt.VIEW); CTShape shape = group.addNewShape(); shape.setId("PowerPlusWaterMarkObject"); shape.setSpid("_x0000_s102"); shape.setType("#_x0000_t136"); // 設置形狀樣式(旋轉,位置,相對路徑等參數(shù)) shape.setStyle(getShapeStyle(fingerText)); shape.setFillcolor(FONT_COLOR); // 字體設置為實心 shape.setStroked(STTrueFalse.FALSE); // 繪制文本的路徑 CTTextPath shapeTextPath = shape.addNewTextpath(); // 設置文本字體與大小 shapeTextPath.setStyle("font-family:" + FONT_NAME + ";font-size:" + FONT_SIZE); shapeTextPath.setString(fingerText); CTPicture pict = ctr.addNewPict(); pict.set(group); } /** * 構建Shape的樣式參數(shù) * * @param fingerText * @return */ private static String getShapeStyle(String fingerText) { StringBuilder sb = new StringBuilder(); // 文本path繪制的定位方式 sb.append("position: ").append("absolute"); // 計算文本占用的長度(文本總個數(shù)*單字長度) sb.append(";width: ").append(fingerText.length() * WIDTH_PER_WORD).append("pt"); // 字體高度 sb.append(";height: ").append("20pt"); sb.append(";z-index: ").append("-251654144"); sb.append(";mso-wrap-edited: ").append("f"); // 設置水印的間隔,這是一個大坑,不能用top,必須要margin-top。 sb.append(";margin-top: ").append(STYLE_TOP); sb.append(";mso-position-horizontal-relative: ").append("page"); sb.append(";mso-position-vertical-relative: ").append("page"); sb.append(";mso-position-vertical: ").append("left"); sb.append(";mso-position-horizontal: ").append("center"); sb.append(";rotation: ").append(STYLE_ROTATION); return sb.toString(); } /** * 將指定的字符串重復repeats次. */ private static String repeatString(String pattern, int repeats) { StringBuilder buffer = new StringBuilder(pattern.length() * repeats); Stream.generate(() -> pattern).limit(repeats).forEach(buffer::append); return new String(buffer); } }
/** * @author lyk * @version 1.0 * @date 2024/1/25 23:16 * @description */ public class Main { public static void main(String[] args) { final String inPath = "src/main/java/com/lyk/finger/doc/aaaa.docx"; final String outPath = "src/main/java/com/lyk/finger/doc/out.docx"; // 添加水印 WatermarkUtil.waterMarkDocXDocument(inPath, outPath, "落魄程序員在線炒粉"); } }
4、OK 完事~
到此這篇關于SpringBoot+POI實現(xiàn)給word添加水印功能的文章就介紹到這了,更多相關SpringBoot POI Word添加水印內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Java實現(xiàn)計網(wǎng)循環(huán)冗余檢驗算法的方法示例
這篇文章主要給大家介紹了關于Java實現(xiàn)計網(wǎng)循環(huán)冗余檢驗算法的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2021-04-04SSH框架網(wǎng)上商城項目第22戰(zhàn)之銀行圖標以及支付頁面顯示
這篇文章主要為大家詳細介紹了SSH框架網(wǎng)上商城項目第22戰(zhàn)之銀行圖標以及支付頁面顯示,感興趣的小伙伴們可以參考一下2016-06-06注冊中心配置了spring?security后客戶端啟動報錯
這篇文章主要為大家介紹了注冊中心配置了spring?security后客戶端啟動報錯問題解決,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-07-07SpringBoot如何優(yōu)雅的整合Swagger Api自動生成文檔
在多人協(xié)作的開發(fā)過程中,API文檔不僅可以減少等待,也能保證開發(fā)的持續(xù)進行,這篇文章主要給大家介紹了關于SpringBoot如何優(yōu)雅的整合Swagger Api自動生成文檔的相關資料,需要的朋友可以參考下2021-07-07SpringBoot+vue+Axios實現(xiàn)Token令牌的詳細過程
Token是在服務端產(chǎn)生的,前端可以使用用戶名/密碼向服務端請求認證(登錄),服務端認證成功,服務端會返回?Token?給前端,Token可以使用自己的算法自定義,本文給大家介紹SpringBoot+vue+Axios實現(xiàn)Token令牌,感興趣的朋友一起看看吧2023-10-10