当前位置: 首页 > news >正文

java实现pdf文件添加水印,下载到浏览器

java实现pdf文件添加水印,下载到浏览器

添加itextpdf依赖

<dependency><groupId>com.itextpdf</groupId><artifactId>itextpdf</artifactId><version>5.5.8</version>
</dependency>

文件下载到浏览器和指定路径

根据需求,不需要指定路径可以删除对应的输出流

public void addPDFImageWaterMark(MultipartFile srcFile, MultipartFile imagePath, HttpServletResponse response) {String fileName = "test.pdf";PdfReader reader = null;PdfStamper stamper = null;FileInputStream fileInputStream = null;//这个输出流要放入PdfStamper构造方法中,这里也会下载一个文件,不需要的话可以在finally中删除FileOutputStream fileOutputStream = null;//下载到你指定的路径,try里面new的路径,不需要下载到指定路径可以删除FileOutputStream fos = null;// 设置响应头,指定内容类型和文件名,准备下载到浏览器,下载到指定位置,不需要下载到浏览器可以删除这个输出流ServletOutputStream outputStream = null;response.setContentType("application/pdf");response.setHeader("Content-Disposition", "attachment; filename=" + srcFile.getOriginalFilename());try {outputStream = response.getOutputStream();//如果是路径的话可以使用另一个构造方法reader = new PdfReader(srcPath);reader = new PdfReader(srcFile.getBytes());fileOutputStream = new FileOutputStream(fileName);stamper = new PdfStamper(reader, fileOutputStream);//加载图片//如果是路径的话可以使用另一个构造方法Image image =Image.getInstance(imagePath);Image image = Image.getInstance(imagePath.getBytes());//将图片控制大小,适配这个大小image.scaleToFit(200, 100);PdfGState gs = new PdfGState();//gs.setFillOpacity(0.2f);//图片水印透明度//gs.setStrokeOpacity(0.4f);//设置笔触字体不透明度PdfContentByte content = null;int total = reader.getNumberOfPages();//pdf文件页数for (int i = 0; i < total; i++) {float x = reader.getPageSize(i + 1).getWidth();//页宽度float y = reader.getPageSize(i + 1).getHeight();//页高度content = stamper.getOverContent(i + 1);content.setGState(gs);content.beginText();//开始写入//每页7行,一行3个for (int j=0; j<3; j++) {for (int k=0; k<7; k++) {//setAbsolutePosition 方法的参数(输出水印X轴位置,Y轴位置)image.setAbsolutePosition(x/3*j-30, y/7*k-20);content.addImage(image);}}content.endText();//结束写入}//要先关闭流才能将生成的文件写到指定地方!!!stamper.close();reader.close();//指定这个文件(这里我用的相对路径)fileInputStream = new FileInputStream(fileName);//创建输出流,下载到指定路径fos = new FileOutputStream("test1.pdf");byte[] buffer = new byte[1024];int bytesRead = 0;while ((bytesRead = fileInputStream.read(buffer)) != -1) {// 浏览器下载outputStream.write(buffer, 0, bytesRead);//下载到指定路径fos.write(buffer, 0, bytesRead);}} catch (Exception e) {e.printStackTrace();} finally {try {//关闭流if (stamper != null) {stamper.close();}if (reader != null) {reader.close();}if (fos != null) {fos.close();}if (fileInputStream != null) {fileInputStream.close();}if (fileOutputStream != null) {fileOutputStream.close();}if (outputStream != null) {outputStream.close();}} catch (Exception e) {e.printStackTrace();}}
}

效果如下:代码中的相对路径在src平级目录下,test.pdf是PdfStamper里面fileOutputStream生成的,test1.pdf是fos生成的

在这里插入图片描述

浏览器下载的如下:

在这里插入图片描述

生成的pdf内容如下(红框里面是pdf原来的内容,可以自己调整代码中注释掉的设置水印透明度来调整)

在这里插入图片描述

提供的前端代码自行测试

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><h2>测试PDF添加水印</h2><form method="post" action="http://localhost:8080/addPDFImageWaterMark" enctype="multipart/form-data"><label for="srcFile">选择PDF文件:</label><input type="file" name="srcFile" id="srcFile" accept=".pdf" required><br><label for="imagePath">选择水印图片:</label><input type="file" name="imagePath" id="imagePath" accept=".jpg, .png" required><br><button type="submit">添加水印并下载</button></form></body>
</html>

相关文章:

java实现pdf文件添加水印,下载到浏览器

java实现pdf文件添加水印&#xff0c;下载到浏览器 添加itextpdf依赖 <dependency><groupId>com.itextpdf</groupId><artifactId>itextpdf</artifactId><version>5.5.8</version> </dependency>文件下载到浏览器和指定路径 …...

代码随想录算法训练营第四十一天丨 动态规划part04

01背包理论基础 见连接&#xff1a;代码随想录 416. 分割等和子集 思路 01背包问题 背包问题&#xff0c;大家都知道&#xff0c;有N件物品和一个最多能背重量为W 的背包。第i件物品的重量是weight[i]&#xff0c;得到的价值是value[i] 。每件物品只能用一次&#xff0c;求解…...

PyCharm免费安装和新手使用教程

简介 PyCharm是一款由JetBrains公司开发的Python集成开发环境&#xff08;IDE&#xff09;。它提供了一系列强大的功能&#xff0c;包括自动代码完成、语法高亮、自动缩进、代码重构、调试器、测试工具、版本控制工具等&#xff0c;使开发者可以更加高效地开发Python应用程序。…...

使用Python的Scikit-Learn进行决策树建模和可视化:以隐形眼镜数据集为例

决策树是一种强大的机器学习算法&#xff0c;它在数据挖掘和模式识别中被广泛应用。决策树模型可以帮助我们理解数据中的模式和规则&#xff0c;并做出预测。在本文中&#xff0c;我们将介绍如何使用Python的Scikit-Learn库构建决策树模型&#xff0c;并使用Graphviz进行可视化…...

开源软件:释放创新的力量,改变数字世界的游戏规则

在充满活力的技术领域&#xff0c;创新是至高无上的&#xff0c;有一种方法已获得显著的吸引力——开源软件。开源软件凭借其透明、协作和无限可能性的精神&#xff0c;彻底改变了我们开发、共享和定制应用程序的方式。从操作系统到数据分析工具&#xff0c;其影响跨越了多个领…...

【QT】鼠标常用事件

新建项目 加标签控件 当鼠标进去&#xff0c;显示【鼠标进入】&#xff0c;离开时显示【鼠标离开】 将QLable提升成自己的控件&#xff0c;然后再去捕获 添加文件 改继承的类名 提升类 同一个父类&#xff0c;可以提升 效果 现在代码就和Qlabel对应起来了。 在.h中声明&…...

LuatOS-SOC接口文档(air780E)--mlx90640 - 红外测温(MLX90640)

常量# 常量 类型 解释 mlx90640.FPS1HZ number FPS1HZ mlx90640.FPS2HZ number FPS2HZ mlx90640.FPS4HZ number FPS4HZ mlx90640.FPS8HZ number FPS8HZ mlx90640.FPS16HZ number FPS16HZ mlx90640.FPS32HZ number FPS32HZ mlx90640.FPS64HZ number FPS6…...

java连接本地数据库可以简写为///

java连接数据库配置文件写为&#xff1a; server:port: 8091 spring:application:name: user-managerdatasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/user?serverTimezoneAsia/Shanghai&characterEncodingutf-8username: root…...

基于springboot漫画动漫网站

基于springbootvue漫画动漫网站 摘要 基于Spring Boot的漫画动漫网站是一个精彩的项目&#xff0c;它结合了现代Web开发技术和漫画爱好者的热情。这个网站的目标是为用户提供一个便捷的平台&#xff0c;让他们能够欣赏各种漫画和动漫作品&#xff0c;与其他爱好者分享他们的兴趣…...

autoFac 生命周期 试验

1.概述 autoFac的生命周期 序号名称说明1InstancePerDependency每次请求都创建一个新的对象2InstancePerLifetimeScope同一个Lifetime生成的对象是同一个实例3SingleInstance每次都用同一个对象 2.注 InstancePerLifetimeScope 同一个Lifetime生成的对象是同一个实例&#x…...

foreach、for in 和for of的区别?

forEach&#xff0c;for...in 和 for...of 是 JavaScript 中用于遍历数据的三种不同的结构。它们在遍历数组、对象和可迭代对象&#xff08;如 Set 和 Map&#xff09;时非常有用。尽管它们都可以用于循环遍历&#xff0c;但它们之间存在一些重要的区别&#xff1a; forEach&a…...

【Effective C++】条款45: 运用成员函数模板接受所有兼容的类型

假设有如下继承结构: class Top{}; class Middle: public Top{}; class Bottom: public Middle{};public继承意味着is-a关系,所有的基类都是派生类,但反之则不是,例如所有的学生都是人,但不是所有的人都是学生. 派生类到基类的指针可以直接隐式转换 Top* pt1 new Middle; T…...

WSL1 安装 debian xfce 用xrdp 导入远程桌面

凑合能用 晃晃行 晃晃不行 而且比较卡 还经常报崩溃 sudo apt install xfce4 xfce4-goodies xorg dbus-x11 x11-xserver-utils apt install locales -y 安装过完应该会提示设置locales&#xff0c;如果安装完之后想要更改相关设置&#xff0c;可以使用如下命令重新设置loca…...

WPF RelativeSource属性-目标对象类型易错

上一篇转载了RelativeSource的三种用法&#xff0c;其中第二种用法较常见&#xff0c;这里记录一下项目中曾经发生错误的地方&#xff0c;以防自己哪天忘记了&#xff0c;又犯了同样错误—WPF RelativeSource属性-CSDN博客 先回顾一下&#xff1a; 控件关联其父级容器的属性—…...

Java while 和do while 循环

循环是程序中的重要流程结构之一。循环语句能够使程序代码重复执行&#xff0c;适用于需要重复一段代码直到满足特定条件为止的情况。 所有流行的编程语言中都有循环语句。Java 中采用的循环语句与C语言中的循环语句相似&#xff0c;主要有 while、do-while 和 for。 另外 Ja…...

应用软件安全编程--03净化传递给 Runtime.exec() 方法的非受信数据

每个 Java 应用都有一个 Runtime 类的实例&#xff0c; 一般需要使用 shell 时调用它&#xff0c;从而可以在 POSIX 中 使用/bin/sh 或者在Windows 平台中使用cmd.exe。 当参数中包含以空格、双引号或者其他以一/开头 的用来表示分支的字符时&#xff0c;就可能发生参数注入攻…...

uniapp阻止冒泡的方法,点击事件嵌套点击事件,怎么阻止同时触发

uniapp阻止冒泡的方法 当我们遇到点击事件嵌套点击事件的时候&#xff0c;点击里边的事件&#xff0c;外边的也会跟着触发该怎么办&#xff1f; 起初我尝试用了css里的修改z-index属性的方法&#xff0c;把里边的<view>标签放在上边&#xff0c;结果两个事件还是同时触发…...

【云原生基础】了解云原生,什么是云原生?

&#x1f4d1;前言 本文主要讲了云原生的基本概念和原则的文章&#xff0c;如果有什么需要改进的地方还请大佬指出⛺️ &#x1f3ac;作者简介&#xff1a;大家好&#xff0c;我是青衿&#x1f947; ☁️博客首页&#xff1a;CSDN主页放风讲故事 &#x1f304;每日一句&#x…...

Android.bp探究

有时不知道Android.bp要咋写&#xff0c;特意看了下源码&#xff1a; ./build/soong/androidmk/androidmk/android.go 简单的Android.bp的模板是下面这个样子&#xff1a; [module type] {name: "[name value]",[property1 name]&#xff1a;"[property1 val…...

【LeetCode】415 字符串相加

415. 字符串相加 给定两个字符串形式的非负整数 num1 和num2 &#xff0c;计算它们的和并同样以字符串形式返回。 你不能使用任何內建的用于处理大整数的库&#xff08;比如 BigInteger&#xff09;&#xff0c; 也不能直接将输入的字符串转换为整数形式。 示例 1&#xff1a…...

Herqles架构:量子比特读取的硬件高效判别器设计与FPGA实现

1. 项目概述&#xff1a;量子比特读取的精度与速度困局在量子计算的世界里&#xff0c;有一个操作看似基础&#xff0c;却直接决定了整个系统的上限&#xff1a;量子比特的读取。你可以把它想象成计算机的“内存读取”指令&#xff0c;但这里读取的不是0或1的确定性电压&#x…...

Edge Impulse:一站式TinyML MLOps平台,破解嵌入式AI开发难题

1. 项目概述&#xff1a;为什么我们需要一个面向TinyML的MLOps平台&#xff1f;如果你尝试过在Arduino、树莓派Pico或者ESP32这类微控制器上跑一个简单的图像分类模型&#xff0c;你大概会立刻理解那种“寸土寸金”的感觉。内存以KB计&#xff0c;算力以MHz计&#xff0c;存储空…...

Rust异步编程实战:构建高性能并发应用

引言 异步编程是构建高性能后端服务的关键技术。作为从Python转向Rust的开发者&#xff0c;我发现Rust的异步模型与Python有很大不同。Rust的异步编程基于协程和事件驱动&#xff0c;通过Tokio运行时实现高效的并发执行。本文将深入探讨Rust异步编程的核心概念、实践模式和性能…...

KV Cache的生老病死:FlashAttention里的显存管理全流程

某团队在昇腾NPU上跑Llama-2-7B-chat&#xff0c;前几个query响应正常&#xff0c;但当对话超过20轮之后&#xff0c;模型开始变得迟钝——生成速度从每秒15个token骤降到每秒2个token。运维查了半天&#xff0c;发现显存占用一直在涨&#xff0c;但batch_size明明没变。 问题出…...

Oracle EBS COA 嵌入 SAP 利润中心段:设计逻辑、哲学、思路、用途、优缺点深度分析

Oracle EBS COA 嵌入 SAP 利润中心段&#xff1a;设计逻辑、哲学、思路、用途、优缺点深度分析先明确核心前提&#xff1a; 你当前场景是集团双系统架构&#xff08;SAPOracle EBS&#xff09;&#xff0c;或Oracle EBS 承接 SAP 迁移 / 数据映射&#xff0c;计划在 EBS 会计科…...

生产环境最佳实践

生产环境最佳实践 前言 本文将介绍Spring Cloud Alibaba在生产环境中的最佳实践&#xff0c;包括配置优化、监控告警、高可用设计等方面。 一、高可用设计 1.1 服务端高可用 # Nacos集群配置 # 至少3个节点 # 推荐使用外部数据库spring:cloud:nacos:server-addr: nacos-1:8848,…...

为什么92%的Midjourney水效渲染失败?——解析v6.1+版本流体折射权重、noise scale与--s值的黄金三角关系

更多请点击&#xff1a; https://codechina.net 第一章&#xff1a;为什么92%的Midjourney水效渲染失败&#xff1f;——问题现象与根本归因 大量用户在使用 Midjourney v6 生成「水效渲染」&#xff08;Water Efficiency Rendering&#xff09;类提示词时遭遇高频失败——表现…...

加拿大AI治理实战:风险分级、监管沙盒与可信AI工程化落地

1. 项目概述&#xff1a;这不是一场技术秀&#xff0c;而是一场制度设计的实战演练“Canada’s AI Ambitions: Navigating the Future of AI Governance”——这个标题里没有一行代码&#xff0c;不提一个模型参数&#xff0c;却直指当前全球AI发展最棘手、最易被忽视的底层命题…...

Spring Boot + MyBatis服务启动流程,新增代码跑通流程,映射规则,常见问题定位

一、服务启动流程 零代码&#xff08;仅需配置文件和依赖&#xff09;。 顺序固定&#xff0c;由框架保证。 一旦某个步骤失败&#xff08;如 XML 解析错误&#xff09;&#xff0c;整个启动失败。 二、新增代码跑通流程 全手动&#xff0c;需熟悉 MyBatis 映射规则、Spring…...

STM32H743音频实战:用CubeMX和I2S驱动WM8978,从寄存器配置到代码移植避坑

STM32H743音频实战&#xff1a;CubeMX与I2S驱动WM8978的深度避坑指南 第一次在STM32H743上调试WM8978音频编解码器时&#xff0c;我盯着示波器上杂乱无章的I2S信号波形发呆了半小时。耳机里偶尔传来的爆裂声仿佛在嘲笑我的无知——这场景想必很多嵌入式音频开发者都不陌生。本文…...