添加pdf水印

下载PDF添加水印

添加图片水印

话不多说,直接开干:

1.导入需要的jar包

<dependency>
	<groupId>com.itextpdf</groupId>
	<artifactId>itextpdf</artifactId>
	<version>5.5.13</version>
</dependency>
<dependency>
	<groupId>com.itextpdf</groupId>
	<artifactId>itext-asian</artifactId>
	<version>5.2.0</version>
</dependency>

itextpdf包为生成pdf的工具包,itext-asian包含了可以了一些字体信息,如果只是添加图片水印可以不导入itext-asian。关于字体,itext除了可以使用itext-asian中的字体,还可以使用ttf字体。

需要注意的是jar包版本之间的兼容,itext在5.0.x版本之前的groupId是com.lowagie,如果用5.0之前版本的itextpdf配合itext-asian,可能导致找不到对应的字体。

2.使用

参考博客:https://www.cnblogs.com/qlqwjy/p/9326468.html

/**
     *
     * @param bos 输出文件的位置
     * @param input
     *            原PDF位置
     * @throws DocumentException
     * @throws IOException
     */
    public static void setWatermark(BufferedOutputStream bos, String input)
            throws DocumentException, IOException {
        PdfReader reader = new PdfReader(input);
        PdfStamper stamper = new PdfStamper(reader, bos);
        int total = reader.getNumberOfPages() + 1;
        PdfGState gs = new PdfGState();
        PdfContentByte content; 
        for (int i = 1; i < total; i++) {
            content = stamper.getOverContent(i);// 在内容上方加水印
            gs.setFillOpacity(0.3f);//设置图片透明度
            content.setGState(gs);
            content.beginText();
            //设置图片水印
            Image image = Image.getInstance("E:/pdfwatermark/150401103429-7.jpg");
            image.setAbsolutePosition(100, 200); // set the first background
            // image of the absolute
            image.scaleToFit(200, 200);          
            content.addImage(image);
            content.endText();

        }
        stamper.close();
}

以上是只针对添加图片水印所作的处理

写上测试代码:

public static void main(String[] args) throws DocumentException, IOException {
        // 要输出的pdf文件
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(new 			File("E:/pdfwatermark/output/abc.pdf")));
        // 将pdf文件先加水印然后输出
        setWatermark(bos, "E:/pdfwatermark/watermarktest.pdf");
}

运行效果:
在这里插入图片描述

实际需求可能还需要添加文字水印,修改setWatermark(BufferedOutputStream bos, String input)方法:

public static void setWatermark(BufferedOutputStream bos, String input)
            throws DocumentException, IOException {
        PdfReader reader = new PdfReader(input);
        PdfStamper stamper = new PdfStamper(reader, bos);
        int total = reader.getNumberOfPages() + 1;
        PdfGState gs = new PdfGState();
        PdfContentByte content;
        BaseFont base = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED);
        for (int i = 1; i < total; i++) {
            content = stamper.getOverContent(i);// 在内容上方加水印
            gs.setFillOpacity(0.3f);
            content.beginText();

            //添加图片水印
            Image image = Image.getInstance("E:/pdfwatermark/150401103429-7.jpg");
            image.setAbsolutePosition(100, 200); // set the first background
            // image of the absolute
            image.scaleToFit(200, 400);
            content.setGState(gs);
            content.addImage(image);
            
			//添加文字水印
            //referenceblog:https://blog.csdn.net/p2073123/article/details/79224833
//            content.setColorFill(Color.LIGHT_GRAY);//error
            content.setColorFill(BaseColor.RED);//字体颜色
            content.setFontAndSize(base, 20);//设置字体样式以及字体大小
            content.setTextMatrix(70, 200);
            content.showTextAligned(Element.ALIGN_CENTER, "公司内部文件,请注意保密!", 0, 20, 180);//设置文字位置,坐标从左下角算起
            content.endText();
        }
        stamper.close();
}

运行main方法查看效果:

在这里插入图片描述
关于字体:
除了可以使用iTextAsian中的字体,还可以使用系统字体文件和或者把字体文件放到项目使用
使用系统字体:

BaseFont.createFont("C:/WINDOWS/Fonts/simsun.ttc", BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED);

把字体文件放到项目使用:

BaseFont.createFont("/simsun.ttc", BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED); //文件可以还可以是ttf文件

相关博客:https://blog.csdn.net/S10011337/article/details/89711008

实现平铺效果

关于文字平铺效果,没有找到可以直接通过设置达到效果的方法,但这部可以通过获取pdf每一页的高度和宽度,再通过循环添加水印的方法达到效果。参考博客:https://blog.csdn.net/qq_33704186/article/details/106442250

下面上代码:

public static void setWatermark(BufferedOutputStream bos, String input)
            throws DocumentException, IOException {
        PdfReader reader = new PdfReader(input);
        PdfStamper stamper = new PdfStamper(reader, bos);
        int total = reader.getNumberOfPages() + 1;
        PdfGState gs = new PdfGState();

        PdfContentByte content;
        BaseFont base = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED);

        int interval = 20;
        // 获取水印文字的最大高度和宽度
        int textH = 0, textW = 0;
        JLabel label = new JLabel();
        label.setText("公司内部文件,请注意保密!");
        FontMetrics metrics = label.getFontMetrics(label.getFont());
        textH = metrics.getHeight();
        textW = metrics.stringWidth(label.getText());
        Rectangle pageSizeWithRotation = null;
        for (int i = 1; i < total; i++) {
            content = stamper.getOverContent(i);// 在内容上方加水印
            gs.setFillOpacity(0.3f);
            content.beginText();

            //添加图片水印
            Image image = Image.getInstance("E:/pdfwatermark/150401103429-7.jpg");
            image.setAbsolutePosition(100, 200); // set the first background
            // image of the absolute
            image.scaleToFit(200, 400);
            content.setGState(gs);
            content.addImage(image);

            //添加文字水印
//            content.setColorFill(Color.LIGHT_GRAY);
//            content.setColorFill(BaseColor.RED);
//            content.setFontAndSize(base, 20);//设置字体样式以及字体大小
//            content.setTextMatrix(70, 200);
//            content.showTextAligned(Element.ALIGN_CENTER, "公司内部文件,请注意保密!", 200, 250, 0);//设置文字位置,坐标从左下角算起

            //获取该页宽度和高度
            pageSizeWithRotation = reader.getPageSizeWithRotation(i);
            float pageHeight = pageSizeWithRotation.getHeight();
            float pageWidth = pageSizeWithRotation.getWidth();
            content.setColorFill(BaseColor.RED);
            content.setFontAndSize(base, 20);//设置字体样式以及字体大小
            // 根据纸张大小多次添加, 水印文字成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, "公司内部文件,请注意保密!", width - textW, height -(textH+10) * 1, 30);
                }
            }
            content.endText();

        }
        stamper.close();
}

运行main方法查看效果:

在这里插入图片描述

对于最后方法中的一些参数可以提取出来进行进一步优化:

最终代码

import com.itextpdf.text.BaseColor;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Image;
import com.itextpdf.text.pdf.*;

import javax.swing.*;
import java.awt.*;
import java.io.IOException;
import java.io.OutputStream;


//参考博客:https://blog.csdn.net/qq_33704186/article/details/106442250
//https://www.cnblogs.com/qlqwjy/p/9326468.html
//https://cloud.tencent.com/developer/article/1472801
//另外一个工具jar https://www.e-iceblue.cn/pdf_java_watermark/java-add-image-watermark-to-pdf.html
//另外一些参考博客 https://www.jianshu.com/p/911d504193cb
// https://blog.csdn.net/weixin_40934096/article/details/100155893
public class WaterMarkUtil {
    /**
     *
     * @param bos 输出文件的位置
     * @param input 原PDF位置
     * @param waterMarkPicPath 水印图片位置
     * @param watermarkWord 水印文字
     * @throws DocumentException
     * @throws IOException
     */
    public static void setWatermark(OutputStream bos, String input, String waterMarkPicPath, String watermarkWord)
            throws DocumentException, IOException {
        PdfReader reader = new PdfReader(input);
        PdfStamper stamper = new PdfStamper(reader, bos);
        int total = reader.getNumberOfPages() + 1;
        PdfGState gs = new PdfGState();

        PdfContentByte content;
        BaseFont base = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED);

        int interval = 20;
        // 获取水印文字的最大高度和宽度
        /*int textH = 0, textW = 0;
        for (int j = 0; j < waterMarkContents.length; j++) {
            JLabel label = new JLabel();
            label.setText(waterMarkContents[j]);
            FontMetrics metrics = label.getFontMetrics(label.getFont());
            if (textH < metrics.getHeight()) {
                textH = metrics.getHeight();
            }
            if (textW < metrics.stringWidth(label.getText())) {
                textW = metrics.stringWidth(label.getText());
            }*/
        int textH = 0, textW = 0;
        JLabel label = new JLabel();
        label.setText(watermarkWord);
        FontMetrics metrics = label.getFontMetrics(label.getFont());
        textH = metrics.getHeight();
        textW = metrics.stringWidth(label.getText());
        com.itextpdf.text.Rectangle pageSizeWithRotation = null;
        for (int i = 1; i < total; i++) {
            content = stamper.getOverContent(i);// 在内容上方加水印
//            content = stamper.getUnderContent(i);//在内容下方加水印
            gs.setFillOpacity(0.3f);
            content.beginText();

            //添加图片水印
            com.itextpdf.text.Image image = Image.getInstance(waterMarkPicPath);
            image.setAbsolutePosition(100, 200); // set the first background
            // image of the absolute
            image.scaleToFit(200, 400);
            content.setGState(gs);//referenceblog:https://blog.csdn.net/p2073123/article/details/79224833
            content.addImage(image);

            //添加文字水印
//            content.setColorFill(Color.LIGHT_GRAY);
//            content.setColorFill(BaseColor.RED);
//            content.setFontAndSize(base, 20);//设置字体样式以及字体大小
//            content.setTextMatrix(70, 200);
//            content.showTextAligned(Element.ALIGN_CENTER, "公司内部文件,请注意保密!", 200, 250, 0);//设置文字位置,坐标从左下角算起

            //获取纸张宽度和高度
            pageSizeWithRotation = reader.getPageSizeWithRotation(i);
            float pageHeight = pageSizeWithRotation.getHeight();
            float pageWidth = pageSizeWithRotation.getWidth();
            content.setColorFill(BaseColor.RED);
            content.setFontAndSize(base, 20);//设置字体样式以及字体大小
            // 根据纸张大小多次添加, 水印文字成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, watermarkWord, width - textW, height -(textH+10) * 1, 30);
                }
            }
            content.endText();

        }
        stamper.close();
    }
}

如果项目为web项目,需要实现浏览器下载,可以在controller中调用该方法时可以将传入的OutputStream改为从HttpServletResponse中获取

controller层代码:

@GetMapping("/downloadPdf")
    public void downloadPdf(HttpServletRequest request, HttpServletResponse response) throws DocumentException, IOException {
        response.addHeader("Content-Disposition", "attachment;filename=" + new String("test.pdf"));
        response.setContentType("application/octet-stream;charset=utf-8");
        WaterMarkUtil.setWatermark(response.getOutputStream(), "E:/pdfwatermark/watermarktest.pdf","E:/pdfwatermark/150401103429-7.jpg","公司内部文件,请注意保密!");
}

参考博客:https://www.cnblogs.com/qlqwjy/p/9326468.html
https://blog.csdn.net/qq_33704186/article/details/106442250

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值