关于加载水印PDF、图片以及压缩包格式文件【把博客当工作记录】

news2024/11/16 0:23:42

写这篇文章的目的是让大家都可以学到东西,核心代码中列出了处理思维和调用方法,业务代码已经过滤掉了,希望大家不要做crud程序员!!要思考。。。该博客不懂时可联系下方。
在这里插入图片描述

1、流程图如下

策略处理图片

2、策略描述

实现方式:
设计模式:父策略调动子策略
业务理念:在不影响原有业务的前提下增加优化
报错机制:当加载logo时报错,直接返回原有文件地址
业务分支:
1、pdf策略:
使用PDDocument处理pdf,主要流程如下
①生成下角PDF(自适应源文件大小)
②拉取源文件到本地
③转换PDF到JPG并合并文件(pdf直接合并会自动分页)
④将转换后的文件重新生成PDF
2、图片策略:
①生成下角PDF(自适应源文件大小)
②拉取源文件到本地
③转换pdf文件成图片并同源文件合并
3、压缩包策略:
根据压缩包的格式走不通的解压 压缩方式
①拉取压缩包到本地
②生成下角PDF
③解压压缩包并将生成的PDF放入
④压缩文件目录

剩余问题(优化性问题):
1、效率问题: 第一次下载文件时,因未处理过需要走策略模式,因处理步骤较多可能会很慢。
2、自适应问题:PDF自适应时会将清晰度降低,目前不走自适应

3、核心代码模块

一、图片格式处理

①生成左小角文件

public void createJpgWithSize(String filePath, float width, float height, Contact contact) {
   
        try (PDDocument document = new PDDocument();
             FileOutputStream fio = new FileOutputStream(new File(filePath))) {
   
            // 创建具有指定大小的页面
            PDPage page = new PDPage(new PDRectangle(width, height));
            try (PDPageContentStream contentStream = new PDPageContentStream(document, page)) {
   
                // 设置字体和颜色
                File fontFile = new File("/data/config/easybii/simhei.ttf");
                PDType0Font font = PDType0Font.load(document, fontFile);
                contentStream.setFont(font, 22);
                contentStream.setNonStrokingColor(Color.black);

                String phone = " ";
                if (StringUtils.isNotBlank(contact.getTelephone())) {
   
                    phone += contact.getTelephone();
                }
                if (StringUtils.isNotBlank(contact.getTelephone1())) {
   
                    phone += "  " + contact.getTelephone();
                }
                // 写入文字
                contentStream.beginText();
                contentStream.newLineAtOffset(20, 15);
                contentStream.showText("报价联系人: " + contact.getName() + phone);
                contentStream.endText();
            }
            // 将页面添加到文档中
            document.addPage(page);
            // 保存文档
            document.save(fio);
        } catch (IOException e) {
   
            e.printStackTrace();
        }
    }

②将pdf文件转化为jpg

  public void convertPDDocumentToImage(String pdfPath, String outputImagePath) {
   
        try (PDDocument document = PDDocument.load(new File(pdfPath))) {
   
            PDFRenderer renderer = new PDFRenderer(document);
            BufferedImage image = renderer.renderImageWithDPI(0, 300); // 0 表示第一页,300 是 DPI

            javax.imageio.ImageIO.write(image, "jpg", new File(outputImagePath));
        } catch (IOException e) {
   
            e.printStackTrace();
        }
    }

③压缩尺寸

 /**
     * 压缩尺寸
     *
     * @param sourceImagePath
     * @param targetImagePath
     * @param targetWidth
     * @param targetHeight
     */
    public void resizeJpg(String sourceImagePath, String targetImagePath, float targetWidth, float targetHeight) {
   
        try {
   
            BufferedImage sourceImage = ImageIO.read(new File(sourceImagePath));

            float sourceWidth = sourceImage.getWidth();
            float sourceHeight = sourceImage.getHeight();

            double scaleX = (double) targetWidth / sourceWidth;
            double scaleY = (double) targetHeight / sourceHeight;
            double scale = Math.min(scaleX, scaleY);

            int newWidth = (int) (sourceWidth * scale);
            int newHeight = (int) (sourceHeight * scale);

            BufferedImage resizedImage = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_RGB);

            Graphics2D graphics2D = resizedImage.createGraphics();
            graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
            graphics2D.drawImage(sourceImage, 0, 0, newWidth, newHeight, null);
            graphics2D.dispose();

            ImageIO.write(resizedImage, "jpg", new FileOutputStream(new File(targetImagePath)));
        } catch (IOException e) {
   
            e.printStackTrace();
        }
    }

④合并俩个图片

/**
     * 将俩张图片合并为一张图片
     *
     * @param image1Path
     * @param image2Path
     * @param mergedImagePath
     */
    public String mergeJpgImages(String image1Path, String image2Path, String mergedImagePath) {
   
        try {
   
            ImageInputStream input1 = ImageIO.createImageInputStream(new File(image1Path));
            ImageReader reader1 = ImageIO.getImageReaders(input1).next();
            reader1.setInput(input1);
            BufferedImage image1 = reader1.read(0);

            ImageInputStream input2 = ImageIO.createImageInputStream(new File(image2Path));
            ImageReader reader2 = ImageIO.getImageReaders(input2).next();
            reader2.setInput(input2);
            BufferedImage image2 = reader2.read(0);

            int width = Math.max(image1.getWidth(), image2.getWidth());
            int height = image1.getHeight() + image2.getHeight();

            BufferedImage mergedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

            // 绘制第一张图片
            mergedImage.getGraphics().drawImage(image1, 0, 0, null);

            // 绘制第二张图片在第一张图片下方
            mergedImage.getGraphics().drawImage(image2, 0, image1.getHeight(), null

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

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

相关文章

【电脑基础硬件】从零开始认识主板

从零开始认识主板 一、主板及其元器件二、主板上的各个部件通信三、主板的选择 注意: 以下以Z790电脑主板为例进行说明。 一、主板及其元器件 IO接口: CPU模块 CPU是电脑的大脑,控制并指挥着电脑的各个模块协同工作。CPU通过主板上的插槽固定…

电路中电阻,电容和电感作用总结

电阻作用 1,上拉电阻 电阻的连接一般是一端接上拉的电源(一般与芯片信号的电压值相匹配),另一端连接芯片引脚所对应的信号大概如下图 功能:一、预置某些引脚的功能,例如复位信号拉高(失能&…

疯传!平台培养“斗士”的背后,是 AI 智能名片与 O2O 商城小程序在搞鬼

摘要:本文探讨了在搭建用户聚集平台以筛选和培养“斗士”的过程中,如何融入 AI 智能名片和 O2O 商城小程序。详细阐述了贴吧或论坛作为初始平台的优势,以及如何通过适当的管理和引导活动筛选出“储备斗士”。同时,分析了 AI 智能名…

浅谈 Mybatis 框架

文章目录 一、什么是MyBatis?1.2、JDBC 二、使用Mybatis2.1、配置MyBatis开发环境2.1.1、配置连接字符串2.1.2、配置MyBatis中的XML路径 2.2、使用MyBatis模式和语法操作数据库 三、使用 Mybatis 进行增删改查操作的要点3.1、ResultMap的用法 四、Mybatis操作难点4.1、#{ } 和…

Modbus-TCP详解

目录 Modbus-TCP Modbus TCP协议的帧结构如下: 实现Modbus-Tcp 使用EasyModbusTCP第三方实现Modbus-Tcp EasyModbusTCP的使用 设置IP 设置端口 设置设备地址 开启通讯 读取寄存器 写入寄存器 实例 Modbus-TCP Modbus TCP是Modbus协议的一种变体,它使用T…

Java多线程的单例设计模式 多种实现方法

目录 前言 饿汉式 懒汉式 Double_check volatile double_check Holder方式 枚举 前言 单例设计模式GOF23中设计模式中最常用的设计模式之一, 单例设计模式提供了多线程环境下的保证唯一实例性的解决方案, 虽然简单, 但是实现单例模式的方式多种多样, 因此需要从多个维度去…

【云原生】恰当运用kubernetes中三种探针,确保应用程序在Kubernetes集群中保持健康、可用和可靠

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,…

Unity热更——ILRuntime安装接入

一、ILRuntime相关地址 1、官网文档地址 2、GitHub上开源的ILRuntime项目工程 3、GitHub上的官方ILRuntime-Unity实例工程 4、官方视频教程-Unity中文课堂(需付费) 5、ILRuntime入门笔记-赵青青-博客园 6、ILRuntime 的学习-简书 二、ILRuntime…

Python | Leetcode Python题解之第324题摆动排序II

题目&#xff1a; 题解&#xff1a; def quickSelect(a: List[int], k: int) -> int:seed(datetime.datetime.now())shuffle(a)l, r 0, len(a) - 1while l < r:pivot a[l]i, j l, r 1while True:i 1while i < r and a[i] < pivot:i 1j - 1while j > l an…

自动生成数据:Navicat 16 让数据测试更高效

文章目录 前言一、Navicat是什么&#xff1f;二、Navicat 16 新功能1. 自动生成数据2. 改进的用户界面3. 云同步 三、 安装指南Windows 版安装macOS 版安装Linux 版安装 四、使用示例&#xff1a;自动生成数据1. 创建连接2. 选择表3. 打开数据生成器4. 设置数据规则5. 生成数据…

top命令实时监测Linux进程

top命令可以动态实时显示Linux进程信息&#xff0c;方便观察频繁换进换出的内存的进程变化。 top命令执行示例如下&#xff1a; 其中&#xff0c;第一行表示系统当前时间、系统的运行时间、登录的用户数目、系统的平均负载&#xff08;最近1分钟&#xff0c;最近5分钟&#xff…

springboot艺体培训机构业务管理系统--论文源码调试讲解

第2章 开发环境与技术 开发艺体培训机构业务管理系统需要搭建编程的环境&#xff0c;也需要通过调查&#xff0c;对各个相关技术进行分析&#xff0c;选取适合本系统开发的技术与工具。 2.1 MySQL数据库 MySQL是一种具有安全系数、安全系数、混合开发性、高效化等特征的轻量…

基于Raft算法的分布式KV数据库:五、剩余部分

github地址&#xff1a;https://github.com/1412771048/Raft CPPRaft系列-剩余部分 首先我们看下第五章的架构图&#xff0c;图中的主要部分我们在前几张讲解完毕了&#xff0c;目前还剩下clerk和k-v数据库&#xff0c;而本篇的重点在于补全版图&#xff0c;完成&#xff1a;…

SQL注入sqli-labs-master关卡一

本文环境搭建使用的是小皮&#xff0c;靶机压缩包&#xff1a;通过百度网盘分享的文件&#xff1a;sqli-labs-php7-master.zip 链接&#xff1a;https://pan.baidu.com/s/1xBfsi2lyrA1QgUWycRsHeQ?pwdqwer 提取码&#xff1a;qwer 下载解压至phpstudy的WWW目录下即可。 第一…

关于Redis的面试题

一、为什么要使用Redis 内存数据库,速度很快工作单线程worker,串行化,原子操作,IO线程是多线程的。避免上下文切换使用 IO模型,天生支撑高并发kv模型,v具有类型结构具有本地方法,计算数据移动二进制安全,value值最大为512MB二、Redis是多线程还是单线程 Redis在6.0版本…

(免费领源码)java#SSM#MYSQL私家车位共享APP 51842-计算机毕业设计项目选题推荐

目 录 摘要 1 绪论 1.1 课题的研究背景 1.2研究内容与研究目标 1.3ssm框架 1.4论文结构与章节安排 2 2 私家车位共享APP系统分析 2.1 可行性分析 2.2 系统流程分析 2.2.1 数据增加流程 2.2.2 数据修改流程 2.2.3数据删除流程 2.3 系统功能分析 2.3.1功能性分析 2…

计算机网络(TCP报文段首部格式中序号和确认号)

TCP首部格式中的序号和确认号并不总是同时出现。 TCP首部的序号和确认号是根据TCP通信的不同阶段和目的来决定的。在建立连接的过程中&#xff0c;序号用于标识发送数据的起始位置&#xff0c;而确认号用于表示接收方期望接收的下一个数据的起始位置。这两个字段在TCP通信的不同…

【vulhub靶场之rsync关】

一、使用nmap模块查看该ip地址有没有Rsync未授权访问漏洞 nmap -p 873 --script rsync-list-modules 加IP地址 查看到是有漏洞的模块的 二、使用rsync命令连接并读取文件 查看src目录里面的信息。 三、对系统中的敏感文件进行下载——/etc/passwd 执行命令&#xff1a; rsy…

【Python】Python中的循环语句

循环语句 导读一、基本概念1.1 循环语句的执行流程1.2 循环语句的分类 二、while语句三、for语句四、break与continue五、死循环六、循环中的else语句七、range()函数结语 导读 大家好&#xff0c;很高兴又和大家见面啦&#xff01;&#xff01;&#xff01; 在上一篇内容中我…

《Advanced RAG》-04-深度研究RAG技术Re-ranking

摘要 文章首先介绍了重新排序在RAG中的重要性&#xff0c;它允许对检索到的文档进行重新排序和过滤&#xff0c;以确保最相关的文档能够被优先考虑&#xff0c;从而提高RAG的效率和准确性。 接着&#xff0c;文章详细描述了两种主流的重新排序方法&#xff1a; 一种是使用重新排…