欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SpringBoot+POI實(shí)現(xiàn)給word添加水印功能

 更新時(shí)間:2024年06月02日 15:10:46   作者:落魄程序員在線炒粉  
這篇文章主要介紹了SpringBoot+POI實(shí)現(xiàn)給word添加水印功能,文中通過代碼示例講解的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下

1、前言

有個(gè)需求:整一個(gè)給 Word 加水印的demo,于是我就網(wǎng)上找唄~
看到那個(gè) Aspose 好像是收費(fèi)的,然后就把目光轉(zhuǎn)向了 POI,看到各種形形色色的也不知道哪個(gè)能用。整了一會(huì),自己拷貝出一個(gè)比較精簡(jiǎn)的能用的 demo 了。

2、人狠話不多,上效果圖

我一般都是直接上圖的,先看效果圖(每一頁都有的):

水印的分布如果不理想,只能小伙伴們自行研究調(diào)整了~

3、人狠話不多,直接來代碼

3.1、我的代碼結(jié)構(gòu)

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";

    /** 一個(gè)字平均長(zhǎng)度,單位pt,用于:計(jì)算文本占用的長(zhǎng)度(文本總個(gè)數(shù)*單字長(zhǎng)度)*/
    private static final Integer WIDTH_PER_WORD = 10;
    /** 與頂部的間距 */
    private static Integer STYLE_TOP = 0;
    /** 文本旋轉(zhuǎn)角度 */
    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("添加水印成功!,一共耗時(shí)" + (System.currentTimeMillis() - beginTime) + "毫秒");

        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (InvalidFormatException e) {
            throw new RuntimeException(e);
        }
    }



    /**
     * 為文檔添加水印
     * @param doc        需要被處理的docx文檔對(duì)象
     * @param fingerText 需要添加的水印文字
     */
    public static void waterMarkDocXDocument(XWPFDocument doc, String fingerText) {
        // 水印文字之間使用8個(gè)空格分隔
        fingerText = fingerText + repeatString(" ", 8);
        // 一行水印重復(fù)水印文字次數(shù)
        fingerText = repeatString(fingerText, 10);
        // 如果之前已經(jīng)創(chuàng)建過 DEFAULT 的Header,將會(huì)復(fù)用
        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è)置形狀樣式(旋轉(zhuǎn),位置,相對(duì)路徑等參數(shù))
        shape.setStyle(getShapeStyle(fingerText));
        shape.setFillcolor(FONT_COLOR);
        // 字體設(shè)置為實(shí)心
        shape.setStroked(STTrueFalse.FALSE);
        // 繪制文本的路徑
        CTTextPath shapeTextPath = shape.addNewTextpath();
        // 設(shè)置文本字體與大小
        shapeTextPath.setStyle("font-family:" + FONT_NAME + ";font-size:" + FONT_SIZE);
        shapeTextPath.setString(fingerText);
        CTPicture pict = ctr.addNewPict();
        pict.set(group);
    }

    /**
     * 構(gòu)建Shape的樣式參數(shù)
     *
     * @param fingerText
     * @return
     */
    private static String getShapeStyle(String fingerText) {
        StringBuilder sb = new StringBuilder();
        // 文本path繪制的定位方式
        sb.append("position: ").append("absolute");
        // 計(jì)算文本占用的長(zhǎng)度(文本總個(gè)數(shù)*單字長(zhǎng)度)
        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");
        // 設(shè)置水印的間隔,這是一個(gè)大坑,不能用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();
    }

    /**
     * 將指定的字符串重復(fù)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 完事~

到此這篇關(guān)于SpringBoot+POI實(shí)現(xiàn)給word添加水印功能的文章就介紹到這了,更多相關(guān)SpringBoot POI Word添加水印內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java實(shí)現(xiàn)計(jì)網(wǎng)循環(huán)冗余檢驗(yàn)算法的方法示例

    Java實(shí)現(xiàn)計(jì)網(wǎng)循環(huán)冗余檢驗(yàn)算法的方法示例

    這篇文章主要給大家介紹了關(guān)于Java實(shí)現(xiàn)計(jì)網(wǎng)循環(huán)冗余檢驗(yàn)算法的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • SSH框架網(wǎng)上商城項(xiàng)目第22戰(zhàn)之銀行圖標(biāo)以及支付頁面顯示

    SSH框架網(wǎng)上商城項(xiàng)目第22戰(zhàn)之銀行圖標(biāo)以及支付頁面顯示

    這篇文章主要為大家詳細(xì)介紹了SSH框架網(wǎng)上商城項(xiàng)目第22戰(zhàn)之銀行圖標(biāo)以及支付頁面顯示,感興趣的小伙伴們可以參考一下
    2016-06-06
  • Java中線程上下文類加載器超詳細(xì)講解使用

    Java中線程上下文類加載器超詳細(xì)講解使用

    這篇文章主要介紹了Java中線程上下文類加載器,類加載器負(fù)責(zé)讀取Java字節(jié)代碼,并轉(zhuǎn)換成java.lang.Class類的一個(gè)實(shí)例的代碼模塊。本文主要和大家聊聊JVM類加載器ClassLoader的使用,需要的可以了解一下
    2022-12-12
  • Java工作中常見的并發(fā)問題處理方法總結(jié)

    Java工作中常見的并發(fā)問題處理方法總結(jié)

    這篇文章主要介紹了Java工作中常見的并發(fā)問題處理方法總結(jié),文章內(nèi)容講解的很清晰,有不太懂得同學(xué)可以跟著學(xué)習(xí)下
    2021-02-02
  • 注冊(cè)中心配置了spring?security后客戶端啟動(dòng)報(bào)錯(cuò)

    注冊(cè)中心配置了spring?security后客戶端啟動(dòng)報(bào)錯(cuò)

    這篇文章主要為大家介紹了注冊(cè)中心配置了spring?security后客戶端啟動(dòng)報(bào)錯(cuò)問題解決,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-07-07
  • IDEA使用入門小白操作教程

    IDEA使用入門小白操作教程

    IntelliJ IDEA,就是Java語言開發(fā)工具 (IDE) 功能與Eclipse同類!本文通過圖文并茂的形式給大家介紹IntelliJ IDEA使用入門教程,非常適合新手小白操作,感興趣的朋友一起看看吧
    2020-10-10
  • SpringBoot如何優(yōu)雅的整合Swagger Api自動(dòng)生成文檔

    SpringBoot如何優(yōu)雅的整合Swagger Api自動(dòng)生成文檔

    在多人協(xié)作的開發(fā)過程中,API文檔不僅可以減少等待,也能保證開發(fā)的持續(xù)進(jìn)行,這篇文章主要給大家介紹了關(guān)于SpringBoot如何優(yōu)雅的整合Swagger Api自動(dòng)生成文檔的相關(guān)資料,需要的朋友可以參考下
    2021-07-07
  • Java 判斷字符串a(chǎn)和b是否互為旋轉(zhuǎn)詞

    Java 判斷字符串a(chǎn)和b是否互為旋轉(zhuǎn)詞

    本篇文章主要介紹了判斷字符串a(chǎn)和b是否互為旋轉(zhuǎn)詞的相關(guān)知識(shí),具有很好的參考價(jià)值。下面跟著小編一起來看下吧
    2017-05-05
  • SpringBoot+vue+Axios實(shí)現(xiàn)Token令牌的詳細(xì)過程

    SpringBoot+vue+Axios實(shí)現(xiàn)Token令牌的詳細(xì)過程

    Token是在服務(wù)端產(chǎn)生的,前端可以使用用戶名/密碼向服務(wù)端請(qǐng)求認(rèn)證(登錄),服務(wù)端認(rèn)證成功,服務(wù)端會(huì)返回?Token?給前端,Token可以使用自己的算法自定義,本文給大家介紹SpringBoot+vue+Axios實(shí)現(xiàn)Token令牌,感興趣的朋友一起看看吧
    2023-10-10
  • JVM 命令行工具的使用

    JVM 命令行工具的使用

    造成Java應(yīng)用出現(xiàn)性能問題的因素非常多,想要定位這些問題,一款優(yōu)秀的性能診斷工具必不可少,本文主要介紹了JVM 命令行工具的使用,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-04-04

最新評(píng)論