java 根据前端传回的png图片数组,后端加水印加密码生成pdf,返回给前端
前端传回的png图片数组,后端加水印加密码生成pdf,返回给前端
- 场景:
- 重点:
- maven依赖
- controller
- service
场景:
当前需求,前端通过html2canvas将页面报表生成图片下载,可以仍然不满意。
需要java后端将前端传过来的图片生成pdf,并且加密码加水印。
重点:
pdf使用A4大小,但是要考虑。根据A4宽高缩放图片后,图片仍然大于A4长度,此时要对图片进行裁剪(2页,3页…)
maven依赖
<!-- pdf文件水印添加 -->
<dependency><groupId>com.itextpdf</groupId><artifactId>itext7-core</artifactId><version>7.1.4</version><type>pom</type>
</dependency>
controller
@PostMapping("/addMarkAndPasswordPdf")@ApiOperation(value = "文件处理-增加水印及密码--入参为文件", notes = "")public void addMarkAndPasswordPdf(@RequestParam("fileStream") MultipartFile[] fileStreams,@RequestParam("filePdfName")String filePdfName, HttpServletRequest request, HttpServletResponse response) {Calendar calendar = Calendar.getInstance();String date = calendar.get(Calendar.YEAR) + "-" + (calendar.get(Calendar.MONTH) + 1);SysUserEntity uc = (SysUserEntity) request.getAttribute("UC");SysUserEntity uc1 = userService.getUserByCode(uc.getUserCode());fileProcessService.fileProcessPdf(fileStreams,filePdfName,uc1,response);}
service
@Overridepublic void fileProcessPdf(MultipartFile[] imageFiles,String filePdfName, SysUserEntity uc, HttpServletResponse response) {response.setHeader("Content-disposition", "attachment;filename=" + filePdfName);// 直接用浏览器或者用postmanresponse.setContentType("application/pdf");response.setCharacterEncoding("utf-8");try {ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();// 创建PDF文档 加密PDF文档PdfWriter writer = new PdfWriter(byteArrayOutputStream,new WriterProperties().setStandardEncryption(// 用户密码uc.getPassword().getBytes(),// 所有者密码uc.getPassword().getBytes(),// 允许的权限EncryptionConstants.ALLOW_PRINTING | EncryptionConstants.ALLOW_COPY,// 加密标准EncryptionConstants.STANDARD_ENCRYPTION_128));PdfDocument pdfDoc = new PdfDocument(writer);Document document = new Document(pdfDoc);// 读取原始图片.按照A4拆分图片,放到pdffor(MultipartFile imageFile: imageFiles){BufferedImage originalImage = ImageIO.read(imageFile.getInputStream());float maxHeight = (PageSize.A4.getHeight()/PageSize.A4.getWidth())*originalImage.getWidth();ArrayList<BufferedImage> cropImageList = cropImageByMaxHeight(originalImage, (int) maxHeight);for (BufferedImage bufferedImage : cropImageList) {// 添加图片PdfPage page = pdfDoc.addNewPage();ByteArrayOutputStream ImageOutputStream = new ByteArrayOutputStream();ImageIO.write(bufferedImage, "png", ImageOutputStream);ImageData imageData = ImageDataFactory.create(ImageOutputStream.toByteArray());com.itextpdf.layout.element.Image image = new com.itextpdf.layout.element.Image(imageData);image.setHorizontalAlignment(HorizontalAlignment.CENTER);document.add(image);ImageOutputStream.close();// 循环为页设置水印setPageWatermark(page, pdfDoc,uc.getCname() + ", " + uc.getDeptTwo(),140);}}// 关闭文档以不再写入内容document.close();pdfDoc.close();writer.close();// 将PDF写入响应输出流response.getOutputStream().write(byteArrayOutputStream.toByteArray());response.getOutputStream().flush();byteArrayOutputStream.close();} catch (Exception e) {e.printStackTrace();log.error(e.getMessage());}}/**** 为PDF页绘画水印* @param pdfPage PDF页对象* @param msg 水印信息* @param interval 水印间隔* @throws IOException 这里的异常是无法获取字体异常*/public static void setPageWatermark(PdfPage pdfPage,PdfDocument pdfDoc, String msg, int interval) throws IOException {// 通过PDF页来构建画布PdfCanvas pdfCanvas = new PdfCanvas(pdfPage);// 中文显示字体
// PdfFont font = PdfFontFactory.createFont("STSong-Light", "UniGB-UCS2-H");float width = pdfPage.getPageSize().getWidth();float height = pdfPage.getPageSize().getHeight();// 开始绘画水印for (int x = 0; x < pdfPage.getPageSize().getWidth(); x += interval) {for (int y = 0; y < pdfPage.getPageSize().getHeight(); y += interval) {Canvas canvas = new Canvas(pdfCanvas, pdfDoc, new Rectangle(0, 0, width, height))// 颜色和透明度.setFontColor(ColorConstants.GRAY, .2f)// 文字样式
// .setFont(font)// 字体大小(具体可以改).setFontSize(20).showTextAligned(msg, x, y, TextAlignment.CENTER,VerticalAlignment.MIDDLE, 19.5f);canvas.close();}}// 释放画布。使用完画布后,请使用此方法。pdfCanvas.release();}/*** 将图片进行裁剪** @param originalImage* @param maxHeight* @return*/public static ArrayList<BufferedImage> cropImageByMaxHeight(BufferedImage originalImage, int maxHeight) {ArrayList<BufferedImage> croppedImages = new ArrayList<>();int originalHeight = originalImage.getHeight();int numImages = originalHeight / maxHeight;int remainder = originalHeight % maxHeight;for (int i = 0; i < numImages; i++) {int y = i * maxHeight;BufferedImage croppedImage = originalImage.getSubimage(0, y, originalImage.getWidth(), maxHeight);croppedImages.add(croppedImage);}// 处理剩余高度(如有)if (remainder > 0) {int y = numImages * maxHeight;BufferedImage croppedImage = originalImage.getSubimage(0, y, originalImage.getWidth(), remainder);croppedImages.add(croppedImage);}return croppedImages;}
成果:
相关文章:

java 根据前端传回的png图片数组,后端加水印加密码生成pdf,返回给前端
前端传回的png图片数组,后端加水印加密码生成pdf,返回给前端 场景:重点:maven依赖controllerservice 场景: 当前需求,前端通过html2canvas将页面报表生成图片下载,可以仍然不满意。 需要java后…...

《探秘鸿蒙Next:如何保障AI模型轻量化后多设备协同功能一致》
在鸿蒙Next的多设备协同场景中,确保人工智能模型轻量化后功能的一致性是一项极具挑战性但又至关重要的任务。以下是一些关键的方法和策略。 统一的模型架构与标准 采用标准化框架:选择如TensorFlow Lite、PyTorch Mobile等在鸿蒙Next上适配良好的轻量化…...

C语言二级
//请编写函数fun(),该函数的功能是:计算并输出给定整数n的所有因 //子(不包括1和自身)之和。规定n的值不大于1000。例如,在主函数 //中从键盘给n输入的值为856,则输出为:sum 763。 //注意&…...

隐私保护+性能优化,RyTuneX 让你的电脑更快更安全
RyTuneX 是一款专为 Windows 10 和 11 用户量身打造的系统优化工具,采用先进的 WinUI 3 框架开发,以其现代化的设计风格和强大的功能集合脱颖而出。这款工具不仅界面简洁美观,还提供了多样化的系统优化选项,旨在帮助用户最大化设备…...

rust学习-宏的定义与使用
rust学习-宏的定义与使用 声明宏(macro_rules! 宏)使用方式1. 简单的宏2. 带参数的宏3. 多个模式的宏 过程宏1. 定义过程宏1.1 属性宏1.2 函数宏1.3 派生宏 2. 使用过程宏2.1 属性宏2.2 函数宏2.3 派生宏 在 Rust 中,宏(macro&…...

【学习总结|DAY032】后端Web实战:登录认证
在 Web 后端开发中,登录认证是保障系统安全和用户数据隐私的关键环节。本文将结合实际开发案例,深入探讨登录功能与登录校验的实现思路和技术细节,希望能帮助读者更好地掌握这一重要知识点。 一、登录功能实现 1.1 思路分析 登录功能的核心…...

leetcode 123. 买卖股票的最佳时机 III
题目:123. 买卖股票的最佳时机 III - 力扣(LeetCode) O(N)的算法: f[i] max(max(0, prices[i] - min(prices[0], prices[1], ... , prices[i - 1)), f[i - 1]); g[i] max(max(0, max(prices[i 1], prices[i 2], ... , pric…...

Apache Tika 详解
Apache Tika是一个开源的、跨平台的库,专门用于检测、提取和解析多种文件格式的元数据。以下是对Apache Tika的详细解析: 一、概述 Apache Tika旨在为各种类型的数据提取提供一个单一的API,它支持多种文件格式,包括文档、图片、…...

ChatGPT被曝存在爬虫漏洞,OpenAI未公开承认
OpenAI的ChatGPT爬虫似乎能够对任意网站发起分布式拒绝服务(DDoS)攻击,而OpenAI尚未承认这一漏洞。 本月,德国安全研究员Benjamin Flesch通过微软的GitHub分享了一篇文章,解释了如何通过向ChatGPT API发送单个HTTP请求…...

Qt——界面优化
在Qt中进行界面优化,可以从以下几个方面入手: 1.使用QWidget:setVisible来控制Widget的 显示和隐藏,而不是删除和重建。 2.使用QPainter直 接绘制组件,避免使用复杂的布局。 3.使用QSS进行样式设置, 减少图片资源的使用。 4.使…...

python学opencv|读取图像(四十一 )使用cv2.add()函数实现各个像素点BGR叠加
【1】引言 前序已经学习了直接在画布上使用掩模,会获得彩色图像的多种叠加效果,相关文章链接为: python学opencv|读取图像(四十)掩模:三通道图像的局部覆盖-CSDN博客 这时候如果更进一步,直接…...

Spring MVC和Spring WebFlux的区别
目录 一、编程模型 二、IO处理方式 三、数据流处理 四、适用场景 五、生态系统 在当今的Web开发领域,Spring框架无疑占据着重要的地位。其中,Spring MVC和Spring WebFlux作为Spring框架中用于构建Web应用程序的两个重要模块,各自具有独特…...

Linux探秘坊-------4.进度条小程序
1.缓冲区 #include <stdio.h> int main() {printf("hello bite!");sleep(2);return 0; }执行此代码后,会 先停顿两秒,再打印出hello bite,但是明明打印在sleep前面,为什么会后打印呢? 因为ÿ…...

Llama 3:开源大模型的里程碑式突破
标题:Llama 3:开源大模型的里程碑式突破 文章信息摘要: Meta通过Llama 3展现了开源LLM的重大突破:采用超大规模训练数据和多阶段训练方法(SFT、rejection sampling、PPO和DPO),突破了传统的Chi…...

计算机网络 (56)交互式音频/视频
一、定义与特点 定义:交互式音频/视频是指用户使用互联网和其他人进行实时交互式通信的技术,包括语音、视频图像等多媒体实时通信。 特点: 实时性:音频和视频数据是实时传输和播放的,用户之间可以进行即时的交流。交互…...

STM32 GPIO工作模式
GPIO工作模式 1. GPIO简介2. GPIO工作模式2.1 输入浮空2.2 输入上拉2.3 输入下拉2.4 模拟2.5 开漏输出2.6 推挽输出2.7 开漏式复用功能2.8 推挽式复用功能 1. GPIO简介 GPIO 是通用输入输出端口的简称,简单来说就是 STM32 可控制的引脚,STM32 芯片的 GPI…...

自动化实现的思路变化
阶段一: 1、成功调用。第一步,一般是用现用的工具,或者脚本成功调用接口 2、解决关联接口的参数传递。有的接口直接,存在参数的传递,一般的思路,就是将这个参数设置为变量。 3、简化代码。总会有些东西是重…...

MongoDB的索引与聚合
一、实验目的 1. 理解索引的概念及其在MongoDB中的重要性和作用。 2. 学习如何选择适合建立索引的字段。 3. 掌握如何创建、删除索引以及如何强制使用索引。 4. 熟悉MongoDB的聚合框架和MapReduce工具,以及简单聚合命令的使用。 二、实验环境准备 1. JAV…...

Java菜鸟养成计划(java基础)--java运算符
java中的运算符 1、java中的运算符1.1 、 、-、 * 、/ 、 %1.2 、、-、 *、/、%1.3 、、--【自增\自减运算符】1.4、>、 <、 > 、< 、 、! 、! 1.5、&&、||、|、&1.6、&、|、~、^1.7、>> 、 <<、>>>位运算1.8、?:三目运算符…...

除了基本的事件绑定,鸿蒙的ArkUI
鸿蒙操作系统(HarmonyOS)是由华为技术有限公司开发的分布式操作系统,旨在为多种智能设备提供一个统一的操作平台。它不仅适用于智能手机,还适用于平板电脑、智能手表、智能电视等物联网设备。为了使开发者能够更加便捷地创建跨设备…...

0164__【GNU】gcc -O编译选项 -Og -O0 -O1 -O2 -O3 -Os
【GNU】gcc -O编译选项 -Og -O0 -O1 -O2 -O3 -Os_gcc -o0-CSDN博客...

vue3组件传值具体使用
问: left.vue文件调用接口获取了后端返回的urlLink字段,我该怎么传递给总的父组件index.vue中,我需要点击父组件的一个按钮来触发跳转? 回答: 在 Vue 3 中使用 TypeScript 和 setup 语法糖时,可以通过 e…...

Web 音视频(二)在浏览器中解析视频
前言 浏览器中已经能直接播放视频,为什么还需要手动写代码解析? 因为,某些场景需要对视频进行更细致的处理,比如截取关键帧、提取视频中的文字、人物打码、极低延时播放视频等等。 总之,除了最单纯的视频播放外&…...

江天科技主要产品销售单价下滑,应收账款、存货周转率大幅下降
《港湾商业观察》廖紫雯 日前,苏州江天包装科技股份有限公司(以下简称:江天科技)冲击北交所,保荐机构为国投证券。 江天科技主要从事标签印刷产品的研发、生产与销售,公司主要产品包括薄膜类和纸张类的不…...

我国的金融组织体系,还有各大金融机构的分类,金融行业的组织
中国金融组织体系介绍 中国金融组织体系是一个复杂而多层次的系统,涵盖了各种类型的金融机构和监管机构。以下是关于中国金融组织体系的详细介绍,包括一行三会等金融监管机构,各大金融机构的分类、涉及的银行以及行业组织。 (一…...

vue md5加密
在Vue中使用MD5加密,你可以使用第三方库如crypto-js。首先,你需要安装这个库: npm install crypto-js --save然后,在你的Vue组件中引入crypto-js并使用其MD5功能: <template><div><input v-model&quo…...

学习ASP.NET Core的身份认证(基于JwtBearer的身份认证7)
本文验证基于请求头中传递token信息的认证方式,webapi项目的控制器类中新建如下函数,仅通过验证的客户端能调用,需要客户端请求在Header中添加’Authorization’: Bearer token’的键值对且通过token验证后才能调用。 [Authorize] [HttpGet]…...

Ubuntu16.04 安装OpenCV4.5.4 避坑
Ubuntu16.04 安装C版OpenCV4.5.4 Ubuntu16.04 VSCode下cmakeclanglldb调试c 文章目录 Ubuntu16.04 安装C版OpenCV4.5.41. 下载Opencv压缩包2. 安装Opencv-4.5.43. 配置OpenCV的编译环境4.测试是否安装成功 1. 下载Opencv压缩包 下载Opencv压缩包,选择source版本。…...

DDD - 整洁架构_解决技术设计困局
文章目录 Pre如何落地 DDD底层技术的更迭 整洁架构的设计主动适配器/北向适配器被动适配器/南向适配器 整洁架构的落地总结 Pre DDD - 软件退化原因及案例分析 DDD - 如何运用 DDD 进行软件设计 DDD - 如何运用 DDD 进行数据库设计 DDD - 服务、实体与值对象的两种设计思路…...

Python自动化运维:一键掌控服务器的高效之道
《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门! 解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 在互联网和云计算高速发展的今天,服务器数量的指数增长使得手动运维和管理变得异常繁琐。Python凭借其强大的可读性和丰富的生态系统,成为…...