使用POI编辑Word文档添加文字水印

目录

  • 背景
  • 依赖
  • 实现代码
  • 效果

背景

近期客户提出一个上传文件时自动添加文字水印的功能,其中关于word文档加水印,网上现有的解决方案都有问题,本文参考java实现word文档(docx)添加水印这篇博客,解决了文档存在分页符情况下无法给所有分页添加水印的问题。
由于POI对于doc格式支持较少,暂时未找到合适的解决doc格式文档添加水印的方法,本文只针对于docx格式文档,如果有大佬有可行方案,欢迎留言交流,感激不尽。

依赖

核心依赖就是POI相关包

<dependency>
    <groupId>org.apache.poigroupId>
    <artifactId>poiartifactId>
    <version>${poi.version}version>
dependency>
<dependency>
    <groupId>org.apache.poigroupId>
    <artifactId>poi-ooxmlartifactId>
    <version>${poi-ooxml.version}version>
dependency>
<dependency>
    <groupId>org.apache.poigroupId>
    <artifactId>poi-ooxml-schemasartifactId>
    <version>${poi-ooxml-schemas.version}version>
dependency>

实现代码

说明:

  • 使用本段代码需要确保服务器正确包含对应字体, 默认使用Arial字体
  • 本段代码参考了POI中org.apache.poi.xwpf.model.XWPFHeaderFooterPolicy#createWatermark的实现
import com.microsoft.schemas.office.office.CTLock;
import com.microsoft.schemas.vml.CTGroup;
import com.microsoft.schemas.vml.CTShape;
import com.microsoft.schemas.vml.CTShapetype;
import com.microsoft.schemas.vml.CTTextPath;
import com.microsoft.schemas.vml.STExt;
import com.microsoft.schemas.vml.STTrueFalse;
import org.apache.poi.util.IOUtils;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFHeader;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTPPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTPicture;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTR;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTRPr;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Paths;

public class DocxTest {

   public void addWatermark(InputStream is, OutputStream os, String waterMark) throws IOException {
       XWPFDocument doc = new XWPFDocument(is);
       // 遍历文档,添加水印
       waterMarkDocxDocument(doc, waterMark);
       try {
           doc.write(os);
       }
       finally {
           IOUtils.closeQuietly(doc);
       }
   }

   /**
    * 为文档添加水印
* 实现参考了{@link org.apache.poi.xwpf.model.XWPFHeaderFooterPolicy#createWatermark(String)} * * @param doc 需要被处理的docx文档对象 * @param waterMark 水印内容 */
private void waterMarkDocxDocument(XWPFDocument doc, String waterMark) { // 获取文档的所有页眉,如果文档没有页眉,则新建一个默认页眉 List<XWPFHeader> headerList = new ArrayList<>(doc.getHeaderList()); if (headerList.isEmpty()) { headerList.add(doc.createHeader(HeaderFooterType.DEFAULT)); } // 遍历所有的header,这里包含所有的分页 for (XWPFHeader header : headerList) { int size = header.getParagraphs().size(); if (size == 0) { header.createParagraph(); } XWPFParagraph paragraph = header.getParagraphArray(0); CTP ctp = paragraph.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"); // 设置形状样式(旋转,位置,相对路径等参数) shape.setStyle(getShapeStyle()); shape.setFillcolor("#d8d8d8"); // 字体设置为实心 shape.setStroked(STTrueFalse.FALSE); // 绘制文本的路径 CTTextPath shapeTextPath = shape.addNewTextpath(); // 设置文本字体与大小 shapeTextPath.setStyle("font-family:Arial;font-size:1pt"); shapeTextPath.setString(waterMark); CTPicture pict = ctr.addNewPict(); pict.set(group); } } /** * 构建Shape的样式参数 */ private String getShapeStyle() { // 文本path绘制的定位方式 return "position: " + "absolute" + ";margin-top: " + 0 + ";width: " + "415pt" + ";height: " + "207.5pt" + ";z-index: " + "-251654144" + ";mso-wrap-edited: " + "f" + ";mso-position-horizontal: " + "center" + ";mso-position-horizontal-relative: " + "margin" + ";mso-position-vertical-relative: " + "margin" + ";mso-position-vertical: " + "center" + ";rotation: " + 315; } public static void main(String[] args) throws IOException { InputStream is = Files.newInputStream(Paths.get("test.docx")); OutputStream os = Files.newOutputStream(Paths.get("testOut.docx")); DocxTest docxTest = new DocxTest(); docxTest.addWatermark(is, os, "WATER MARK"); } }

效果

使用POI编辑Word文档添加文字水印_第1张图片

你可能感兴趣的:(java,apache)