Add file watermark to Word/PPT/PDF/Excel based on POI

foreword

In Web projects, MS Office documents sometimes require encryption or permission restrictions. In addition to restricting and modifying passwords for documents, it is generally necessary to add watermarks to achieve the effect of traceability.
This article completes the watermarking operation for common MS Office documents (Word/PPT/PDF/Excel) based on POI.

technical points

The basic steps of adding a document watermark are to first generate the corresponding image according to the requirement, and then insert the image through the method provided by the corresponding MS Office document object.
Different documents provide different interfaces, some have their own methods for writing watermarks, some need to refer to third-party components, and some need to use awt to generate and write images.

Add watermark to Word document

XWPFHeaderFooterPolicy Official Documentation

public static void addWordWaterMark(String inputPath, String outPath, String markStr) {
    
    
		// 读取原始文件
        File inputFile = new File(inputPath);
        XWPFDocument doc = null;
        try {
    
    
            doc = new XWPFDocument(new FileInputStream(inputFile));
        } catch (FileNotFoundException var24) {
    
    
            throw new RuntimeException("源文件不存在");
        } catch (IOException var25) {
    
    
            throw new RuntimeException("读取源文件IO异常");
        } catch (Exception var26) {
    
    
            throw new RuntimeException("不支持的文档格式");
        }
		// 使用自带工具类完成水印填充
        XWPFHeaderFooterPolicy headerFooterPolicy = doc.getHeaderFooterPolicy();
        headerFooterPolicy.createWatermark(markStr);
        // 设置文档只读
        doc.enforceReadonlyProtection();
        // 生成输出文件
        File file = new File(outPath);
        if (!file.exists()) {
    
    
            try {
    
    
                file.createNewFile();
            } catch (IOException var23) {
    
    
                throw new RuntimeException("创建输出文件失败");
            }
        }
		// 打开输出流,将doc写入输出文件
        OutputStream os = null;
        try {
    
    
            os = new FileOutputStream(outPath);
            doc.write(os);
        } catch (FileNotFoundException var21) {
    
    
            throw new RuntimeException("创建输出文件失败");
        } catch (Exception var22) {
    
    
            throw new RuntimeException("添加文档水印失败");
        } finally {
    
    
            if (os != null) {
    
    
                try {
    
    
                    os.close();
                } catch (IOException var20) {
    
    
                    var20.printStackTrace();
                }
            }
        }
    }

Add watermark to PPT document

The domestic PPT component is used: Spire-Presentation-JAVA, but the component downloaded from the official website will have a free version limit, please decide whether to use it or not.

Spire-Presentation-JAVA official website
official tutorial - add text watermark


public static void addPptWaterMark(String inputPath, String outPath, String markStr) {
    
    
        //加载PPT源文档
        Presentation ppt = new Presentation();
		// 设置PPT密码
        ppt.encrypt("Ka_ze");
        try {
    
    
            ppt.loadFromFile(inputPath);
            ISlide slide = null;
            //获取指定幻灯片
            for (int o = 0; o < ppt.getSlides().getCount(); o++) {
    
    
                slide = ppt.getSlides().get(o);
                //设置文本水印文本宽和高
                int width= 110;
                int height= 80;

                //起始坐标
                float x = 10;
                float y = 40;
                for (int i = 0; i < 4; i++)
                {
    
    
                    for (int j = 0; j < 4; j++)
                    {
    
    
                        //绘制文本,设置文本格式并将其添加到第一张幻灯片
                        // 定义一个长方形区域
                        Rectangle2D.Double rect = new Rectangle2D.Double(x,y,width, height);
                        // 添加一个shape到定义区域
                        IAutoShape shape = slide.getShapes().appendShape(ShapeType.RECTANGLE, rect);
                        // 设置shape样式
                        shape.getFill().setFillType(FillFormatType.NONE);
                        shape.getShapeStyle().getLineColor().setColor(Color.white);
                        shape.setRotation(-45);
                        shape.getLocking().setSelectionProtection(true);
                        shape.getLine().setFillType(FillFormatType.NONE);
                        // 添加文本到shape
                        shape.getTextFrame().setText(markStr);
                        shape.setShapeArrange(ShapeAlignmentEnum.ShapeArrange.SendToBack);
                        // 设置文本水印样式
                        PortionEx textRange = shape.getTextFrame().getTextRange();
                        textRange.getFill().setFillType(FillFormatType.SOLID);
                        textRange.getFill().getSolidColor().setColor(new Color(Integer.parseInt("#C5CBCF".substring(1), 16)));
                        textRange.setFontHeight(20);
                        // 设置下一个水印的横坐标
                        x += (100 + ppt.getSlideSize().getSize().getWidth()/6);
                    }
                    x = 30;
                    // 设置下一个水印的纵坐标
                    y += (100 + ppt.getSlideSize().getSize().getHeight()/7) ;
                }
            }

            //保存文档
            ppt.saveToFile(outPath, FileFormat.PPTX_2013);
            ppt.dispose();
        } catch (Exception e) {
    
    
            e.printStackTrace();
        }
    }

Add watermark to PDF document

Using the open source component iText, it can be used to create and manipulate PDF documents.

Maven Warehouse
Official Documentation-itext-v7.0.0
Official Github

<!-- 引入中文字体支持 -->
<dependency>
     <groupId>com.itextpdf</groupId>
     <artifactId>itext-asian</artifactId>
     <version>5.2.0</version>
 </dependency>
 <!-- 引入组件 -->
 <dependency>
     <groupId>com.itextpdf</groupId>
     <artifactId>itextpdf</artifactId>
     <version>5.4.3</version>
 </dependency>

public static void addPDFWaterMark(String input, String output, String waterMarkName) {
    
    
        BufferedOutputStream bos = null;
        try {
    
    
        	// 读取文件,生成reader
            com.itextpdf.text.pdf.PdfReader reader = new com.itextpdf.text.pdf.PdfReader(input);
            // 生成输出文件,开启输出流
            bos = new BufferedOutputStream(new FileOutputStream(new File(output)));
            // 读取输出流,生成stamper(印章)
            com.itextpdf.text.pdf.PdfStamper stamper = new com.itextpdf.text.pdf.PdfStamper(reader, bos);
			// 设置stamper加密
            stamper.setEncryption(null, "Ka_ze".getBytes(StandardCharsets.UTF_8), PdfWriter.ALLOW_PRINTING, PdfWriter.STANDARD_ENCRYPTION_128);

            // 获取总页数 +1, 下面从1开始遍历
            int total = reader.getNumberOfPages() + 1;
            // 使用classpath下面的字体库
            com.itextpdf.text.pdf.BaseFont base = null;
            try {
    
    
                base = com.itextpdf.text.pdf.BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", com.itextpdf.text.pdf.BaseFont.EMBEDDED);
            } catch (Exception e) {
    
    
                // 日志处理
                e.printStackTrace();
            }

            // 间隔
            int interval = -15;
            // 获取水印文字的高度和宽度
            int textH = 0, textW = 0;
            JLabel label = new JLabel();
            label.setText(waterMarkName);
            FontMetrics metrics = label.getFontMetrics(label.getFont());
            textH = metrics.getHeight();
            textW = metrics.stringWidth(label.getText());      

            // 设置水印透明度
            com.itextpdf.text.pdf.PdfGState gs = new com.itextpdf.text.pdf.PdfGState();
            gs.setFillOpacity(0.2f);
            gs.setStrokeOpacity(0.7f);

            com.itextpdf.text.Rectangle pageSizeWithRotation = null;
            PdfContentByte content = null;
            for (int i = 1; i < total; i++) {
    
    
                // 在内容上方加水印
                content = stamper.getOverContent(i);
                // 在内容下方加水印
                // content = stamper.getUnderContent(i);
                content.saveState();
                content.setGState(gs);

                // 设置字体和字体大小
                content.beginText();
                content.setFontAndSize(base, 20);

                // 获取每一页的高度、宽度
                pageSizeWithRotation = reader.getPageSizeWithRotation(i);
                float pageHeight = pageSizeWithRotation.getHeight();
                float pageWidth = pageSizeWithRotation.getWidth();

                // 根据纸张大小多次添加, 水印文字成30度角倾斜
                for (int height = interval + textH; height < pageHeight; height = height + textH * 6) {
    
    
                    for (int width = interval + textW; width < pageWidth + textW; width = width + textW * 2) {
    
    
                        content.showTextAligned(Element.ALIGN_LEFT, waterMarkName, width - textW, height - textH, 30);
                    }
                }
                content.endText();
            }

            // 关流
            stamper.close();
            reader.close();
        } catch (DocumentException | IOException e) {
    
    
            e.printStackTrace();
        }
    }


Add watermark to Excel document

Set image properties using Graphics2D from the awt package.


private static void addExcelWaterMark(String inputSrc, String outputSrc, String waterMarkName) {
    
    
		 // 读取水印文字
		 String[] textArray = waterMark.split("\n");
		 // 设置字体
		 Font font = new Font("microsoft-yahei", Font.PLAIN, 20);
		 // 单元水印图片宽高
		 int width = 500;
		 int height = 200;
		 
		 // 缓冲区图片对象
		 BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
 		 // 基于特定宽高,创建图形对象
		 Graphics2D g = image.createGraphics();
		 // 基于图形对象生成半透明图片
		 image = g.getDeviceConfiguration().createCompatibleImage(width, height, Transparency.TRANSLUCENT);
		 // 释放画笔
		 g.dispose();
		 
		 // 基于半透明图片,创建图形对象
		 g = image.createGraphics();
		 // 设置图形颜色
		 g.setColor(new Color(Integer.parseInt("#C5CBCF".substring(1), 16)));
		 // 设置图形字体
		 g.setFont(font);
		 // 设置图形倾斜度
		 g.shear(0.1, -0.26);
		 // 设置字体平滑
		 g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
		 // 画出字符串
		 int y = 150;
		 for (int i = 0; i < textArray.length; i++) {
    
    
		     g.drawString(textArray[i], 0, y);
		     y = y + font.getSize();
		 }
		 // 释放画笔
		 g.dispose();

        ByteArrayOutputStream os = new ByteArrayOutputStream();
        try {
    
    
        	// 将内存中的图片写入至输出流
            ImageIO.write(image, "png", os);
            // 读取原文档
            XSSFWorkbook workbook = new XSSFWorkbook(new FileInputStream(inputSrc));
            // 将图片输出流写入Excel
            int pictureIdx = workbook.addPicture(os.toByteArray(), Workbook.PICTURE_TYPE_PNG);
            // 获取工作簿中的图片对象
            POIXMLDocumentPart poixmlDocumentPart = workbook.getAllPictures().get(pictureIdx);


            for (int i = 0; i < workbook.getNumberOfSheets(); i++) {
    
    //获取每个Sheet表
                XSSFSheet sheet = workbook.getSheetAt(i);
                PackagePartName ppn = poixmlDocumentPart.getPackagePart().getPartName();
                String relType = XSSFRelation.IMAGES.getRelation();
                // 为当前Sheet添加图片关系
                PackageRelationship pr = sheet.getPackagePart().addRelationship(ppn, TargetMode.INTERNAL, relType, null);
                // 将图片关系添加到Sheet底层结构中
                sheet.getCTWorksheet().addNewPicture().setId(pr.getId());
            }
            try {
    
    
                workbook.write(new FileOutputStream(outputSrc));
            } finally {
    
    
                os.close();
            }
        } catch (Exception e) {
    
    
            e.printStackTrace();
        }
    }

Guess you like

Origin blog.csdn.net/Ka__ze/article/details/131881795