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. pdfUtil
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 {
                //自己的字体资源路径
                Resource resource = new ClassPathResource("template/msyh.ttf");
                byte[] fileBytes = IoUtil.readBytes(resource.getInputStream());
//                String path = "src/main/resources/template/msyh.ttf"; //绝对路径只在开发工具下有效
//                baseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED); //设置字体为itext自带字体
                baseFont = BaseFont.createFont("msyh.ttf", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED, true, fileBytes, null, false);//设置自定义字体
            } 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());
    }
  1. BaseFont方法 设置中文字体
  • 直接引用itxtPdf字体
  • 引用自定义字体
    自定义字体需要注意点:
    1. 直接从windows复制字体 C:\Windows\Fonts 下,字体文件可能存在多个 参数名称传参需要逗号分隔加数字
      BaseFont baseFont = BaseFont.createFont(“msyh.ttf,0”, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED, true, fileBytes,null, false);
    2. spring项目中,如果放在静态文件区只能读取流的方式读取文件,路径也不能使用绝对路径或相对路径

版权声明:本文为weixin_43836438原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。