itextPdf pdf加水印

通过itextpdf 给pdf文件加水印

  1. pom文件添加依赖
        <!-- 目前有7版本的,5版本的已停止维护 -->
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itextpdf</artifactId>
            <version>5.5.13.3</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.itextpdf/itext-asian -->
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itext-asian</artifactId>
            <version>5.2.0</version>
        </dependency>
  1. 编码
package com.cybx.extendedinsurance.system.util;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.http.HttpUtil;
import com.easybao.exception.ValidException;
import com.itextpdf.text.BaseColor;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.pdf.*;
import org.apache.commons.lang.StringUtils;
import reactor.util.function.Tuple5;
import reactor.util.function.Tuples;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.function.Consumer;
import java.util.function.Supplier;

/**
 * @Author Shixing.Feng
 * @Date 2022/8/23
 * @DESC pdf相关操作
 */
public class PdfUtil {

    /**
     * pdf文件增加水印
     *
     * @param url http地址或者文件路径
     */
    public static void addTextWaterMark(String url, OutputStream targetOutPut, String waterMarkWorld, Supplier<BaseFont> baseFontSupplier,
                                        Consumer<Tuple5<PdfReader, PdfStamper, PdfGState, BaseFont, String>> contextStyleConsumer) {
        try {
            //获取文件输入流
            BufferedInputStream inputStream = getSource(url);
            //读取文件
            PdfReader reader = new PdfReader(inputStream);
            PdfStamper stamper = new PdfStamper(reader, targetOutPut);
            BaseFont baseFont = baseFontSupplier.get();
            PdfGState gs = new PdfGState();
            contextStyleConsumer.accept(Tuples.of(reader, stamper, gs, baseFont, waterMarkWorld));
            stamper.close();
        } catch (IOException e) {
            e.printStackTrace();
            throw new ValidException("读取pdf文件异常,异常原因 " + e.getMessage());
        } catch (DocumentException d) {
            d.printStackTrace();
            throw new ValidException("绑定输出和阅读器出错, 错误原因 " + d.getMessage());
        } finally {

        }
    }

    /**
     * 将传入的http或者文件路径转为输出流
     *
     * @param url
     * @return
     */
    public static BufferedInputStream getSource(String url) {
        if (StringUtils.isEmpty(url)) {
            throw new ValidException("url地址不能为空");
        }
        if (HttpUtil.isHttp(url) || HttpUtil.isHttps(url)) {
            byte[] fileBytes = HttpUtil.downloadBytes(url);
            return new BufferedInputStream(IoUtil.toStream(fileBytes));
        } else if (FileUtil.isFile(url)) {
            return FileUtil.getInputStream(url);
        }
        throw new ValidException("不支持的文件类型");
    }


    public static Supplier<BaseFont> defaultBaseFont() {
        return () -> {
            // 使用iTextAsian.jar中的字体
            BaseFont baseFont = null;
            try {
                baseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
            } catch (Exception e) {
                e.printStackTrace();
                throw new ValidException("设置水印字体失败,失败原因" + e.getMessage());
            }
            // 使用Windows系统字体(TrueType)
//            BaseFont baseFont = BaseFont.createFont("C:/Windows/Fonts/SIMYOU.TTF", BaseFont.IDENTITY_H,
//                    BaseFont.NOT_EMBEDDED);
            return baseFont;
        };
    }

    public static Consumer<Tuple5<PdfReader, PdfStamper, PdfGState, BaseFont, String>> defaultContextStyleConsumer() {
        return (Tuple5<PdfReader, PdfStamper, PdfGState, BaseFont, String> consumer) -> {
            // 获取PDF页数
            int total = consumer.getT1().getNumberOfPages();
            // 遍历每一页
            for (int i = 0; i < total; i++) {
                // 内容
                PdfContentByte content = consumer.getT2().getOverContent(i + 1);
                // 页宽度
                float width = consumer.getT1().getPageSize(i + 1).getWidth();
                // 页高度
                float height = consumer.getT1().getPageSize(i + 1).getHeight();
                //开始写入文本
                content.beginText();
                consumer.getT3().setFillOpacity(0.3f);
                //水印透明度
                content.setGState(consumer.getT3());
                content.setColorFill(BaseColor.LIGHT_GRAY);
                //字体大小
                int fontSize = 48;
                content.setFontAndSize(consumer.getT4(), fontSize);
                //设置字体的输出位置 A4大小 595,842
//                content.setTextMatrix(70, 200);
                //倾斜角度
                float rotation = 30f;
                int spacing = (int) (fontSize * consumer.getT5().length());
                int num = (int) Math.ceil((double) (height) / spacing);
                for (int j = 0; j < num; j++) {
                    //需要生成多少行
                    int marginLeft = -(int) (Math.random() * fontSize * consumer.getT5().length());
                    int colSpacing = (int) (fontSize * consumer.getT5().length());
                    while (marginLeft < width) {
                        //需要生成多少列
                        content.showTextAligned(Element.ALIGN_JUSTIFIED_ALL, consumer.getT5(), marginLeft, spacing * j, rotation);
                        marginLeft += colSpacing;
                    }
                }
                //结束写入文本
                content.endText();
                /* 要打图片水印的话 */
            /* Image image = Image.getInstance("c:/1.jpg");
                content.addImage(image); */
            }
        };
    }


}
  1. 主方法调用
 public static void main(String[] args) {
        ByteArrayOutputStream targetOutPut = new ByteArrayOutputStream();
        PdfUtil.addTextWaterMark("文件url", targetOutPut, "水印内容",
                PdfUtil.defaultBaseFont(), PdfUtil.defaultContextStyleConsumer());
    }

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


学习编程是顺着互联网的发展潮流,是一件好事。新手如何学习编程?其实不难,不过在学习编程之前你得先了解你的目的是什么?这个很重要,因为目的决定你的发展方向、决定你的发展速度。
IT行业是什么工作做什么?IT行业的工作有:产品策划类、页面设计类、前端与移动、开发与测试、营销推广类、数据运营类、运营维护类、游戏相关类等,根据不同的分类下面有细分了不同的岗位。
女生学Java好就业吗?女生适合学Java编程吗?目前有不少女生学习Java开发,但要结合自身的情况,先了解自己适不适合去学习Java,不要盲目的选择不适合自己的Java培训班进行学习。只要肯下功夫钻研,多看、多想、多练
Can’t connect to local MySQL server through socket \'/var/lib/mysql/mysql.sock问题 1.进入mysql路径
oracle基本命令 一、登录操作 1.管理员登录 # 管理员登录 sqlplus / as sysdba 2.普通用户登录
一、背景 因为项目中需要通北京网络,所以需要连vpn,但是服务器有时候会断掉,所以写个shell脚本每五分钟去判断是否连接,于是就有下面的shell脚本。
BETWEEN 操作符选取介于两个值之间的数据范围内的值。这些值可以是数值、文本或者日期。
假如你已经使用过苹果开发者中心上架app,你肯定知道在苹果开发者中心的web界面,无法直接提交ipa文件,而是需要使用第三方工具,将ipa文件上传到构建版本,开...
下面的 SQL 语句指定了两个别名,一个是 name 列的别名,一个是 country 列的别名。**提示:**如果列名称包含空格,要求使用双引号或方括号:
在使用H5混合开发的app打包后,需要将ipa文件上传到appstore进行发布,就需要去苹果开发者中心进行发布。​
+----+--------------+---------------------------+-------+---------+
数组的声明并不是声明一个个单独的变量,比如 number0、number1、...、number99,而是声明一个数组变量,比如 numbers,然后使用 nu...
第一步:到appuploader官网下载辅助工具和iCloud驱动,使用前面创建的AppID登录。
如需删除表中的列,请使用下面的语法(请注意,某些数据库系统不允许这种在数据库表中删除列的方式):
前不久在制作win11pe,制作了一版,1.26GB,太大了,不满意,想再裁剪下,发现这次dism mount正常,commit或discard巨慢,以前都很快...
赛门铁克各个版本概览:https://knowledge.broadcom.com/external/article?legacyId=tech163829
实测Python 3.6.6用pip 21.3.1,再高就报错了,Python 3.10.7用pip 22.3.1是可以的
Broadcom Corporation (博通公司,股票代号AVGO)是全球领先的有线和无线通信半导体公司。其产品实现向家庭、 办公室和移动环境以及在这些环境...
发现个问题,server2016上安装了c4d这些版本,低版本的正常显示窗格,但红色圈出的高版本c4d打开后不显示窗格,
TAT:https://cloud.tencent.com/document/product/1340