java pdf加水印

news2024/11/19 11:18:48

本文将Base64编码形式的pdf文件加水印,并输出完成后的pdf的Base64编码,也可以根据情况自行改动,输出其他形式的内容。

首先引入两个包

        <!-- PDF文件依赖包 -->
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itextpdf</artifactId>
            <version>5.5.13.1</version>
        </dependency>
        <!-- PDF文件字体 防止中文乱码 -->
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itext-asian</artifactId>
            <version>5.2.0</version>
        </dependency>

 完整代码如下:

package com;

import com.itextpdf.text.Element;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfGState;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;


public class testPdf {

    public static void main(String[] args) {

        try {

            String pdfBase64 = "JVBERi0xLjQKJeLjz9MKMiAwIG9iago8PC9MZW5ndGggOTEvRmlsdGVyL0ZsYXRlRGVjb2RlPj5zdHJlYW0KeJwr5HIK4TI2U7AwMFMISeEyUNA1tAAx9N0MFQyNFELSuDQ8UnNy8hXC84tyUhSpytYMyQJaaIBirwYN7Bm1c9DaiVVLQUoadRF9bCHbRiTFriFcgVwADhAu8AplbmRzdHJlYW0KZW5kb2JqCjQgMCBvYmoKPDwvVHlwZS9QYWdlL01lZGlhQm94WzAgMCA1OTUgODQyXS9SZXNvdXJjZXM8PC9Gb250PDwvRjEgMSAwIFI+Pj4+L0NvbnRlbnRzIDIgMCBSL1BhcmVudCAzIDAgUj4+CmVuZG9iagoxIDAgb2JqCjw8L1R5cGUvRm9udC9TdWJ0eXBlL1R5cGUxL0Jhc2VGb250L0hlbHZldGljYS9FbmNvZGluZy9XaW5BbnNpRW5jb2Rpbmc+PgplbmRvYmoKMyAwIG9iago8PC9UeXBlL1BhZ2VzL0NvdW50IDEvS2lkc1s0IDAgUl0+PgplbmRvYmoKNSAwIG9iago8PC9UeXBlL0NhdGFsb2cvUGFnZXMgMyAwIFI+PgplbmRvYmoKNiAwIG9iago8PC9Qcm9kdWNlcihpVGV4dK4gNS41LjEzLjEgqTIwMDAtMjAxOSBpVGV4dCBHcm91cCBOViBcKEFHUEwtdmVyc2lvblwpKS9DcmVhdGlvbkRhdGUoRDoyMDIzMDcwNjE0NTUzOCswOCcwMCcpL01vZERhdGUoRDoyMDIzMDcwNjE0NTUzOCswOCcwMCcpPj4KZW5kb2JqCnhyZWYKMCA3CjAwMDAwMDAwMDAgNjU1MzUgZiAKMDAwMDAwMDI4NCAwMDAwMCBuIAowMDAwMDAwMDE1IDAwMDAwIG4gCjAwMDAwMDAzNzIgMDAwMDAgbiAKMDAwMDAwMDE3MiAwMDAwMCBuIAowMDAwMDAwNDIzIDAwMDAwIG4gCjAwMDAwMDA0NjggMDAwMDAgbiAKdHJhaWxlcgo8PC9TaXplIDcvUm9vdCA1IDAgUi9JbmZvIDYgMCBSL0lEIFs8YTRkYTc4NmQ5MTllZDllMTg2NzQ0MDJlMDMwYWJhNzk+PGE0ZGE3ODZkOTE5ZWQ5ZTE4Njc0NDAyZTAzMGFiYTc5Pl0+PgolaVRleHQtNS41LjEzLjEKc3RhcnR4cmVmCjYyOAolJUVPRgo=";
            String waterMarkName = "这是测试水印";


            BASE64Decoder base64Decoder = new BASE64Decoder();
            byte[] decodeBuffer = base64Decoder.decodeBuffer(pdfBase64);
            String outBase64 = PDFAddWatermark(pdfBase64, waterMarkName);
            // 为了验证结果方便,直接转为文件到本地
            FileOutputStream fos = new FileOutputStream("C:\\Users\\zh\\Desktop\\a.pdf");
            fos.write(base64Decoder.decodeBuffer(outBase64));
            fos.close();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 给PDF添加水印
     * @param pdfBase64 原文件base64编码
     * @param waterMarkName 添加水印的内容
     */
    public static String PDFAddWatermark(String pdfBase64, String waterMarkName) throws Exception {
        // 每页水印行数
        int row = 7;
        // 每行水印个数
        int col = 3;
        // 旋转角度
        float rotation = 30f;
        BASE64Decoder base64Decoder = new BASE64Decoder();
        byte[] decodeBuffer = base64Decoder.decodeBuffer(pdfBase64);
        // 读取PDF
        PdfReader reader = new PdfReader(decodeBuffer);
        //创建字节数组输出流
        ByteArrayOutputStream ous =new ByteArrayOutputStream();
        // 创建字节缓冲输出流
        BufferedOutputStream bos = new BufferedOutputStream(ous);
        // 输出的PDF文件内容
        PdfStamper stamper = new PdfStamper(reader, bos);
        BaseFont base = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED);
        PdfGState gs = new PdfGState();
        gs.setFillOpacity(0.2f);//改透明度
        gs.setStrokeOpacity(0.4f);//设置笔触字体不透明度

        PdfContentByte content;
        int total = reader.getNumberOfPages();//pdf文件页数
        for (int i=0; i<total; i++) {
            // 在内容上方加水印
            content = stamper.getOverContent(i+1);
            // 在内容下方加水印
            // content = stamper.getUnderContent(i+1);
            //开始写入
            content.beginText();
            content.setGState(gs);
            //字体大小
            content.setFontAndSize(base, 20);
            //每页7行,一行3个
            for (int j=0; j<col; j++) {
                for (int k=0; k<row; k++) {
                    float x = reader.getPageSize(i+1).getWidth() / col * j + 90;
                    float y = reader.getPageSize(i+1).getHeight() / row * k;
                    //showTextAligned 方法的参数(文字对齐方式,位置内容,输出水印X轴位置,Y轴位置,旋转角度)
                    content.showTextAligned(Element.ALIGN_CENTER, waterMarkName, x, y, rotation);
                }
            }
            // 添加水印文字
            content.endText();
        }
        stamper.close();
        //添加水印后pdf的base64
        byte[] bytes = ous.toByteArray();
        ous.close();
        bos.close();
        reader.close();
        return new BASE64Encoder().encode(bytes);
    }

}

结果展示a.pdf:

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/726552.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

计算机体系结构基础知识介绍之缓存性能的十大进阶优化之编译器优化和硬件预取(六)

优化七&#xff1a;编译器优化&#xff0c;降低miss率 处理器和主内存之间不断扩大的性能差距促使编译器编写者仔细检查内存层次结构&#xff0c;看看编译时优化是否可以提高性能。再次&#xff0c;研究分为指令缺失的改进和数据缺失的改进。接下来介绍的优化可以在许多现代编…

步入JAVA——环境搭建与项目通览

前言 在这篇文章中&#xff0c;荔枝会介绍如何配置Java后端开发环境并借助一个Java web项目简单介绍一下Java的后端开发逻辑。与python的后端开发逻辑是类似的&#xff0c;Java的后端开发其实也是通过一个个类来实现的。对于像荔枝这种小白白来说&#xff0c;入门的第一个练手J…

java项目之高校四六级报名管理系统(ssm+jsp+mysql)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于ssm的高校四六级报名管理系统。项目源码以及部署相关请联系风歌&#xff0c;文末附上联系信息 。 &#x1f495;&#x1f495;作者&#xff1a;风歌…

mysql执行顺序以及为什么别名不能用在 where 后

1、mysql执行顺序 如下&#xff1a; 1. from 阶段 2. where 阶段 3. group by 阶段 4. having 阶段 5. select 阶段 6. order by 阶段 7. limit 阶段 2、为什么别名不能用在 where 后

微信小程序反编译之后运行报错“_typeof3 is not a function”

微信小程序解包之后&#xff0c;在微信开发者工具当中点开调试器&#xff0c;选择Console选项卡&#xff0c;发现左侧的预览界面是空白的&#xff0c;虽然真机调试可以有显示&#xff0c;但是真机预览也是跟左边的界面一样都是空白。之后发现Console里面显示 解决方法&#x…

7.5~7.6学习成果总结

关于封装&#xff0c;满足几个原则&#xff0c;一般的成员变量用privat修饰&#xff0c;仅暴露少量方法获取&#xff0c;如果是内部的操作方法也用private&#xff0c;除非是希望被全局使用&#xff0c;的才考虑用public&#xff0c;如果是进希望被子类用的话可以考虑用protect…

ICG NH2,1686147-55-6,吲哚菁绿氨基,安全性更好,并具有更好的光稳定性

ICG NH2&#xff0c;ICG-Amine&#xff0c;吲哚菁绿氨基|&#xff08;文章编辑来源于&#xff1a;西安凯新生物科技有限公司小编WMJ&#xff09;产品结构式&#xff1a; 对于ICG NH2&#xff08;1686147-55-6&#xff09;我们需要知道这些&#xff1a; CAS号为1686147-55-6&am…

专项练习21

目录 一、选择题 1、下列逻辑表达式的结果为false的是&#xff08;&#xff09; 2、请问以下JS代码输出的结果是什么&#xff1f; 3、以下哪些对象是Javascript内置的可迭代对象&#xff1f; 二、编程题 1、找到数组参数中的最大值并返回。注意&#xff1a;数组中只包含数字 …

16 直线识别拟合角平分线(matlab程序)

1.简述 直线检测是数字图像处理的重要内容,在道路识别,建筑物识别,医学图像分析等领域都有十分重要的应用。通过对已经获得的图像进行边缘检测,然后用Hough变换对边缘检测进行直线检测。该方法简单,受直线中的间隙和噪声影响较小。在Matlab环境下对该方法进行了仿真实验,并对图…

【LLM】Windows本地CPU部署民间版中文羊驼模型(Chinese-LLaMA-Alpaca)踩坑记录

目录 前言 准备工作 Git Python3.9 Cmake 下载模型 合并模型 部署模型 前言 想必有小伙伴也想跟我一样体验下部署大语言模型, 但碍于经济实力, 不过民间上出现了大量的量化模型, 我们平民也能体验体验啦~, 该模型可以在笔记本电脑上部署, 确保你电脑至少有16G运行…

1.4 计算机网络性能

1.4 计算机网络性能 速率带宽延迟/时延(delay或latency)四种分组延迟排队延迟 时延带宽积分组丢失&#xff08;丢包&#xff09;吞吐量/率&#xff08;Throughput&#xff09; 速率 速率即数据率(data rate)或称数据传输速率或比特率(bit rate) 单位时间&#xff08;秒&#x…

为什么我心中TOP1的编程语言是Java?我为什么选择Java?

文章目录 前言优点跨平台性面向对象编程&#xff08;OOP&#xff09;强大的类库和工具支持广泛的应用领域 缺点速度相对较慢内存消耗较大较高的学习曲线 Java 学习路线总结前置知识Web前端基础 后端基础1. Java基础2. 数据库技术3. Web开发技术4. 框架技术5. 服务器部署 其他技…

KKT条件

有两种情况&#xff1a; 原问题是非凸函数原问题是凸函数 &#xff08;1&#xff09;非凸函数 KKT是强对偶的必要条件&#xff0c;而不是充分条件&#xff0c;即KKT不能推出强对偶。 &#xff08;2&#xff09;凸函数 KKT与强对偶互为充要条件。 下面给出具体的KKT条件&a…

数据结构--二叉树的先中后序遍历

数据结构–二叉树的先中后序遍历 二叉树的遍历 层次遍历 层次遍历:基于树的层次特性确定的次序规则 二叉树的递归特性: ①要么是个空二叉树 ②要么就是由“根节点左子树右子树”组成的二叉树 先 \color{red}先 先序遍历&#xff1a; 根 \color{red}根 根左右&#xff08; N \…

springboot 集成log4j日志,需要自定义json格式内容输出方便ES采集

背景 公司需要将服务迁移到K8S环境上&#xff0c;由于目前服务输出的格式不符合ES进行采集的日志格式&#xff0c;所有需要将日志输出的格式进行调整为JSON格式&#xff0c;方便ES采集 遇到的坑 之前是直接配置的输出格式的message为"message": %msg"&#x…

记录一下,linux安装环境步骤。

前文 鉴于之前都是下载压缩包方式安装环境&#xff0c;学习了docker之后&#xff0c;决定将服务器初始化&#xff0c;重新用docker安装相应环境 条件&#xff1a;自己买的阿里云centos系统。单核系统&#xff0c;仅学习使用。 初始化云盘 初始化云盘步骤&#xff1a; 1&…

Perfetto 命令行工具(Android 10 及更高版本)

Perfetto 命令行工具&#xff08;Android 10 及更高版本&#xff09; 1、快速入门1.1 启动跟踪服务1.2 记录跟踪1.2.1 通过 Perfetto UI 记录跟踪1.2.2 通过 cmdline 记录跟踪1.2.3 System Tracing 的系统级应用抓取 2、perfetto 工具2.1 数据源选择2.2 语法参数2.2.1 轻量模式…

数据结构--树和二叉树

目录 1.树的结构及概念1.1树的概念1.2树的相关概念1.3树的表示1.4树在实际中的运用&#xff08;表示文件系统的目录结构&#xff09; 2.二叉树的相关概念2.1概念2.2现实版的二叉树2.3特殊的二叉树2.4二叉树的性质2.5二叉树的存储结构 3.与二叉树有关的习题总结 1.树的结构及概念…

RabbitMQ系列(14)--Topics交换机的简介与实现

1、Topics交换机的介绍 Topics交换机能让消息只发送往绑定了指定routingkey的队列中去&#xff0c;不同于Direct交换机的是&#xff0c;Topics能把一个消息往多个不同的队列发送&#xff1b;Topics交换机的routingkey不能随意写&#xff0c;必须是一个单词列表&#xff0c;并以…

leetcode极速复习版-第三章哈希表

目录 哈希表 哈希表理论基础 242.有效的字母异位词 349. 两个数组的交集 202. 快乐数 1. 两数之和 454.四数相加II 383. 赎金信 15. 三数之和 18. 四数之和 哈希表 哈希表理论基础 那么哈希表能解决什么问题呢&#xff0c;一般哈希表都是用来快速判断一个元素是否出…