PDF下载添加水印和访问密码
下载接口
@ApiOperation(value = "下载文件-pdf", notes = "下载文件pdf版", httpMethod = "GET", response = WebResult.class)@RequestMapping(value = "/downloadPdf", method = RequestMethod.GET)public void downloadFilePdf(@RequestParam(name = "id") String id,@RequestParam(name = "fileExt", defaultValue = "", required = false) String fileExt,@RequestParam(name = "fileName", defaultValue = "", required = false) String fileName,@RequestParam(name = "userName", defaultValue = "", required = false) String userName,@RequestParam(name = "key", defaultValue = "", required = false) String key,HttpServletRequest request, HttpServletResponse response) throws Exception {String fileId = fileInfoService.getFileIdByMainId(id, fileExt);GridFSFile gfsfile = mongoDbFileService.getFSFile(fileId);String realFileName = gfsfile.getFilename().replace(",", "");if (StrUtil.isEmpty2(fileName)) {fileName = realFileName;} else {fileName = fileName.concat(".").concat(FileUtil.getFileExt(realFileName));}//处理中文文件名乱码if (request.getHeader("User-Agent").toUpperCase().contains("MSIE") ||request.getHeader("User-Agent").toUpperCase().contains("TRIDENT")|| request.getHeader("User-Agent").toUpperCase().contains("EDGE")) {fileName = java.net.URLEncoder.encode(fileName, "UTF-8");} else {//非IE浏览器的处理:fileName = new String(fileName.getBytes("UTF-8"), "ISO-8859-1");}// 通知浏览器进行文件下载int lastDotIndex = fileName.lastIndexOf('.');String fileNameWithoutExtension = fileName.substring(0, lastDotIndex);response.setHeader("Content-Disposition", "attachment;filename=\"" + fileNameWithoutExtension +".pdf" + "\"");// 获取pdf文件,并添加水印在返回pdf// todo 获取用户名,解决中文水印报错bugString watermark = "";DateTime date = DateUtil.date();String time = DateUtil.format(date, "yyyy-MM-dd");watermark = watermark + time+ "" + userName;OutputStream out = response.getOutputStream();PdfUtil.two(tempPathPdf+id+".pdf",out,key,watermark);}
工具类
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.encryption.AccessPermission;
import org.apache.pdfbox.pdmodel.encryption.StandardProtectionPolicy;
import org.apache.pdfbox.pdmodel.font.PDType0Font;
import org.apache.pdfbox.pdmodel.font.PDType1Font;
import org.apache.pdfbox.util.Matrix;import java.io.File;
import java.io.IOException;
import java.io.OutputStream;/*** @author csb* @description: TODO* @date 2023/11/20 17:05*/
public class PdfUtil {//加密和加水印public static void two (String in, OutputStream out, String password, String watermark) throws IOException {// 加载PDF文件PDDocument document = PDDocument.load(new File(in));// 创建访问权限对象AccessPermission accessPermission = new AccessPermission();accessPermission.setCanPrint(true);accessPermission.setCanModify(false);accessPermission.setCanFillInForm(false);accessPermission.setCanExtractContent(false);// 创建保护策略对象StandardProtectionPolicy protectionPolicy = new StandardProtectionPolicy("password", password, accessPermission);// 应用保护策略到文档document.protect(protectionPolicy);//加载本地字体文件,解决中文bug PDType0Font font = PDType0Font.load(document, new File("D:\\11.ttf"));// 加水印 遍历每一页for (PDPage page : document.getPages()) {// 创建内容流以在页面上绘制文本PDPageContentStream contentStream = new PDPageContentStream(document, page, PDPageContentStream.AppendMode.APPEND, true);// 设置字体、颜色和透明度contentStream.setFont(font, 36);contentStream.setNonStrokingColor(200, 200, 200); // 灰色contentStream.setLineWidth(5);// 计算水印位置(居中)float pageHeight = page.getMediaBox().getHeight();float pageWidth = page.getMediaBox().getWidth();// 添加水印文本contentStream.beginText();for (int h = 10; h < pageHeight; h = h + 300) {for (int w = -10; w < pageWidth; w = w + 300) {contentStream.setTextMatrix(Matrix.getRotateInstance(0.4, w, h));contentStream.showText(watermark);}}contentStream.endText();contentStream.restoreGraphicsState();// 关闭内容流并保存更改contentStream.close();}// 保存加密后的PDF文件document.save(out);// 关闭文档document.close();out.close();}public static void WatermarkPDF(String in) throws IOException {// 加载PDF文档PDDocument document = PDDocument.load(new File("input.pdf"));// 遍历每一页for (PDPage page : document.getPages()) {// 创建内容流以在页面上绘制文本PDPageContentStream contentStream = new PDPageContentStream(document, page, PDPageContentStream.AppendMode.APPEND, true);// 设置字体、颜色和透明度contentStream.setFont(PDType1Font.HELVETICA_BOLD, 36);contentStream.setNonStrokingColor(200, 200, 200); // 灰色contentStream.setLineWidth(5);// 计算水印位置(居中)float x = page.getMediaBox().getWidth() / 2;float y = page.getMediaBox().getHeight() / 2;// 添加水印文本contentStream.beginText();contentStream.newLineAtOffset(x, y);contentStream.showText("水印");contentStream.endText();// 关闭内容流并保存更改contentStream.close();}// 保存带有水印的PDF文档document.save("output.pdf");// 关闭文档document.close();}public static void SetPdfPassword (String in){try {// 加载PDF文件PDDocument document = PDDocument.load(new File(in));// 创建访问权限对象AccessPermission accessPermission = new AccessPermission();accessPermission.setCanPrint(true);accessPermission.setCanModify(false);accessPermission.setCanFillInForm(false);accessPermission.setCanExtractContent(false);// 创建保护策略对象StandardProtectionPolicy protectionPolicy = new StandardProtectionPolicy("password", "123456", accessPermission);// 应用保护策略到文档document.protect(protectionPolicy);// // 保存加密后的PDF文件document.save("D:\\test\\pdf\\2.pdf");// 关闭文档document.close();} catch (IOException e) {e.printStackTrace();}}}
maven
<dependency><groupId>org.apache.pdfbox</groupId><artifactId>pdfbox</artifactId><version>2.0.6</version>
</dependency><dependency><groupId>com.artofsolving</groupId><artifactId>jodconverter</artifactId><version>2.2.1</version>
</dependency>
相关文章:
PDF下载添加水印和访问密码
下载接口 ApiOperation(value "下载文件-pdf", notes "下载文件pdf版", httpMethod "GET", response WebResult.class)RequestMapping(value "/downloadPdf", method RequestMethod.GET)public void downloadFilePdf(RequestPar…...

基于SSM+MySQL的的新闻发布系统设计与实现
目录 项目简介 项目技术栈 项目运行环境 项目截图 代码截取 源码获取 项目简介 新闻发布系统是一款基于Servletjspjdbc的网站应用程序,旨在提供一个全面且高效的新闻发布平台。该系统主要包括后台管理和前台新闻展示两个平台,涵盖了新闻稿件的撰写…...
记录首次使用yolov8-obb
1.数据格式 之前使用的数据格式是yolov5_obb的数据格式,然后需要转数据格式: 目前的数据只支持四个坐标点标注的数据,参考:If a corner of the rotate rectangle is out of the image range, How to annotate the image? Issu…...

深度学习环境配置:Anaconda 安装和 pip 源
conda是一种通用包管理系统,与pip的使用类似,环境管理则允许用户方便地安装不同版本的python并可以快速切换。 Anaconda则是一个打包的集合,里面预装好了conda、某个版本的python、众多packages、科学计算工具等等,就是把很多常用…...
100 个 NLP 面试问题
100 个 NLP 面试问题 一、 说明 对于技术磨练中,其中一项很酷的技能培训是提问。不知道答案并没有多大的错;错就错在不谷歌这些疑问。本篇就是在面试之前,您将此文档复制给自己,做一个系统的模拟实战。 二、经典NLP问题(共8题&a…...

C# OMRON PLC FINS TCP协议简单测试
FINS(factory interface network service)通信协议是欧姆龙公司开发的用于工业自动化控制网络的指令/响应系统。运用 FINS指令可实现各种网络间的无缝通信,包括用于信息网络的 Etherne(以太网),用于控制网络的Controller Link和SYSMAC LINK。…...

MQTT在linux下服务端和客户端的应用
MQTT(Message Queuing Telemetry Transport)是一种轻量级、开放标准的消息传输协议,设计用于受限设备和低带宽、不稳定网络的通信。 MQTT的一些关键特点和概念: 发布/订阅模型: MQTT采用发布/订阅(Publ…...
韦达定理用处多
文章目录 前言一、一元二次方程中根和系数之间的关系二、韦达定理的数学推导和作用1. 韦达定理的数学推导2. 韦达定理的作用 三、韦达定理的应用举例1. 解题示例12. 解题示例23. 解题示例34. 解题示例45. 解题示例56. 解题示例67. 解题示例7 总结 前言 韦达定理说明了一元n次方…...
Kotlin-类
构造函数 Java final File file new File("file.txt");Kotlin val file File("file.txt")类 Java public final class User { }Kotlin class User公开类 Java public class User { }Kotlin open class User属性类 Java final class User {pri…...
redis基本数据结构介绍
Redis(Remote Dictionary Server)是一个开源的高性能键值对数据库,它支持多种数据结构,包括字符串、哈希、列表、集合、有序集合等。这些数据结构为开发者提供了丰富的数据操作方式,使得Redis在缓存、消息队列、排行榜…...
云数据库RDS云监控
1. 什么是云数据库RDS?它有哪些特点? 云数据库RDS是一种在线关系型数据库服务,它具备的特点包括: 安全可靠:提供了容灾、备份、恢复等高可用性功能,确保数据的安全与可靠。弹性伸缩:用户可以根…...

全自动网页生成系统重构版源码
全自动网页生成系统重构版源码分享,所有模板经过精心审核与修改,完美兼容小屏手机大屏手机,以及各种平板端、电脑端和360浏览器、谷歌浏览器、火狐浏览器等等各大浏览器显示。 为用户使用方便考虑,全自动网页制作系统无需繁琐的注…...

Leetcode—33. 搜索旋转排序数组【中等】
2024每日刷题(110) Leetcode—33. 搜索旋转排序数组 实现代码 class Solution { public:int search(vector<int>& nums, int target) {int n nums.size();int l 0, r n - 1;while(l < r) {int m l (r - l) / 2;if(nums[m] target) …...

vulhub中Apache APISIX Dashboard API权限绕过导致RCE(CVE-2021-45232)
Apache APISIX是一个动态、实时、高性能API网关,而Apache APISIX Dashboard是一个配套的前端面板。 Apache APISIX Dashboard 2.10.1版本前存在两个API/apisix/admin/migrate/export和/apisix/admin/migrate/import,他们没有经过droplet框架的权限验证&…...
JavaSE习题 使用函数求最大值、求最大值方法的重载和求和方法的重载
目录 1 使用函数求最大值2 求最大值方法的重载3 求和方法的重载 1 使用函数求最大值 使用函数求最大值:创建方法求两个数的最大值max2,随后再写一个求3个数的最大值的函数max3。 要求: 在max3这个函数中,调用max2函数ÿ…...

英码科技携手昇腾共建算力底座:推出EA500I超强AI处理能力边缘计算盒子!
在数字经济浪潮中,算力已成为不可或缺的驱动力,为各行各业的数字化转型提供了强大的推动力。面对多元化和供需不平衡的挑战,需要实现从理论架构到软硬件实现的质的飞跃,以满足持续增长的算力需求,华为昇腾在这一方面展…...

蓝桥杯每日一题-----数位dp练习
题目 链接 参考代码 写了两个,一个是很久以前写的,一个是最近刚写的,很久以前写的时候还不会数位dp所以写了比较详细的注释,这两个代码主要是设置了不同的记忆数组,通过这两个代码可以理解记忆数组设置的灵活性。 im…...

JS(react)图片压缩+图片上传
上传dome var fileNodeTakeStock: any createRef();<inputref{fileNodeTakeStock}onChange{showPictureTakeStock}style{{ display: "none" }}id"fileInpBtn"type"file"accept"image/*" //限制上传格式multiple{false}capture&qu…...
WPF DispatcherTimer用法
System.Windows.Threading.DispatcherTimer 类主要用于WPF应用程序中进行周期性任务调度,并且保证这些任务在UI线程上执行。 这对于需要更新界面或与UI元素交互的定时操作非常有用,因为WPF的所有UI操作都必须在主线程(即Dispatcher线程&…...

【网络安全实验】snort实现高级IDS
注:本实验分别使用kali和CentOS6.8进行测试,可惜的是使用kali进行实验过程中遇到了困难,未能完成完整实验,而使用CentOS6.8成功完成了完整实验。 实验中用到的软件: https://download.csdn.net/download/weixin_5255…...

超短脉冲激光自聚焦效应
前言与目录 强激光引起自聚焦效应机理 超短脉冲激光在脆性材料内部加工时引起的自聚焦效应,这是一种非线性光学现象,主要涉及光学克尔效应和材料的非线性光学特性。 自聚焦效应可以产生局部的强光场,对材料产生非线性响应,可能…...

阿里云ACP云计算备考笔记 (5)——弹性伸缩
目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...
QMC5883L的驱动
简介 本篇文章的代码已经上传到了github上面,开源代码 作为一个电子罗盘模块,我们可以通过I2C从中获取偏航角yaw,相对于六轴陀螺仪的yaw,qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...
Java多线程实现之Callable接口深度解析
Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...
06 Deep learning神经网络编程基础 激活函数 --吴恩达
深度学习激活函数详解 一、核心作用 引入非线性:使神经网络可学习复杂模式控制输出范围:如Sigmoid将输出限制在(0,1)梯度传递:影响反向传播的稳定性二、常见类型及数学表达 Sigmoid σ ( x ) = 1 1 +...
鸿蒙DevEco Studio HarmonyOS 5跑酷小游戏实现指南
1. 项目概述 本跑酷小游戏基于鸿蒙HarmonyOS 5开发,使用DevEco Studio作为开发工具,采用Java语言实现,包含角色控制、障碍物生成和分数计算系统。 2. 项目结构 /src/main/java/com/example/runner/├── MainAbilitySlice.java // 主界…...

ABAP设计模式之---“简单设计原则(Simple Design)”
“Simple Design”(简单设计)是软件开发中的一个重要理念,倡导以最简单的方式实现软件功能,以确保代码清晰易懂、易维护,并在项目需求变化时能够快速适应。 其核心目标是避免复杂和过度设计,遵循“让事情保…...

VM虚拟机网络配置(ubuntu24桥接模式):配置静态IP
编辑-虚拟网络编辑器-更改设置 选择桥接模式,然后找到相应的网卡(可以查看自己本机的网络连接) windows连接的网络点击查看属性 编辑虚拟机设置更改网络配置,选择刚才配置的桥接模式 静态ip设置: 我用的ubuntu24桌…...

七、数据库的完整性
七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...

GruntJS-前端自动化任务运行器从入门到实战
Grunt 完全指南:从入门到实战 一、Grunt 是什么? Grunt是一个基于 Node.js 的前端自动化任务运行器,主要用于自动化执行项目开发中重复性高的任务,例如文件压缩、代码编译、语法检查、单元测试、文件合并等。通过配置简洁的任务…...