java实现根据Velocity批量生成pdf并合成zip压缩包

Velocity 模版操作

用的之前写好的: 传送门

其中需要新加一个转成输入流的方法

    public static InputStream convertToPdf(StringWriter stringWriter) throws IOException {//将 HTML 转为字节流byte[] htmlBytes = stringWriter.toString().getBytes(StandardCharsets.UTF_8);//创建 PDF 输出流ByteArrayOutputStream pdfOutputStream = new ByteArrayOutputStream();try (PdfWriter writer = new PdfWriter(pdfOutputStream);PdfDocument pdfDocument = new PdfDocument(writer)) {// 设置 A4 纸张和边距pdfDocument.setDefaultPageSize(PageSize.A4);pdfDocument.setTagged(); // 支持无障碍阅读//配置中文字体ConverterProperties properties = new ConverterProperties();FontProvider fontProvider = new FontProvider();fontProvider.addFont("STSongStd-Light", "UniGB-UCS2-H"); // 添加中文字体properties.setFontProvider(fontProvider);//转换 HTML 到 PDFtry (InputStream htmlStream = new ByteArrayInputStream(htmlBytes)) {HtmlConverter.convertToPdf(htmlStream, pdfDocument, properties);}}// 返回 PDF 的输入流return new ByteArrayInputStream(pdfOutputStream.toByteArray());}

具体使用

public void reportBatchDownload(ReportBatchDownload params, HttpServletResponse response) {List<SpeExamineInfo> infos = speExamineInfoMapper.selectListByReportBatchDownload(params);if (infos.isEmpty()) {throw new ServiceException("当前没有已完成的预约记录");}String filName = "体检报告.zip";// 设置请求流try {FileUtils.setAttachmentResponseHeader(response, filName);response.setContentType("application/zip");try (ZipOutputStream zipOut = new ZipOutputStream(response.getOutputStream(), StandardCharsets.UTF_8)) {for (SpeExamineInfo info : infos) {VelocityContext velocityContext = getVelocityContext(info.getId(), info, null);StringWriter stringWriter = VelocityUtils.genHtml(velocityContext, "vm/report.vm");try (InputStream inputStream = VelocityUtils.convertToPdf(stringWriter)) {// 添加ZIP条目zipOut.putNextEntry(new ZipEntry(buildFilePath(info)));// 写入文件内容byte[] cache = new byte[8192];int nRead;while ((nRead = inputStream.read(cache)) != -1) {zipOut.write(cache, 0, nRead);}zipOut.closeEntry();}zipOut.flush();}// 最后刷新缓冲区zipOut.finish();}} catch (IOException e) {throw new RuntimeException("生成压缩包失败", e);}}private String buildFilePath(SpeExamineInfo info){return "/" + info.getSchName() + "/" + info.getGradeName() + "/" + info.getClassName() + "/" + info.getStuName() + "_体检报告.pdf";}// 处理vm模版变量
private VelocityContext getVelocityContext(String infoId, SpeExamineInfo speExamineInfo, String imgPrefix) {SpeExamineResQuery speExamineResQuery = new SpeExamineResQuery();speExamineResQuery.setInfoId(infoId);List<SpeExamineResDto> speExamineResDtos = speExamineResMapper.selectList(speExamineResQuery);SpeExamineType speExamineType = new SpeExamineType();speExamineType.setInfoId(infoId);List<SpeExamineType> speExamineTypes = speExamineTypeMapper.selectList(speExamineType);Map<String, Object> res = new HashMap<>();speExamineResDtos.forEach(item -> {if (StringUtils.isNotBlank(item.getItemResLabel())) {res.put(item.getItemCode() + "_label", item.getItemResLabel());}res.put(item.getItemCode(), item.getItemRes());res.put(item.getItemCode() + "_conclusion", item.getConclusion());res.put(item.getItemCode() + "_hasException", item.getHasException());});Map<String, Object> type = new HashMap<>();speExamineTypes.forEach(item -> {type.put(item.getItemType() + "_advice", item.getDocAdvice());type.put(item.getItemType() + "_signature", (StringUtils.isNotBlank(imgPrefix) ? imgPrefix : "" ) + item.getDocSign());});Map<String, Object> param = new HashMap<>(3);param.put("info", speExamineInfo);param.put("res", res);param.put("type", type);VelocityContext velocityContext = new VelocityContext();velocityContext.put("pdf", param);return velocityContext;}

效果图

在这里插入图片描述
在这里插入图片描述

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

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

相关文章

SCDN能够运用在物联网加速当中吗?

在当今的科技化时代当中&#xff0c;物联网已经广泛渗透在各个领域行业当中&#xff0c;随着物联网规模的不断扩大&#xff0c;数据信息的传输速度和网络稳定性成为企业需要重视的两点因素&#xff0c;而SCDN也成为安全内容分发网络作为一种融合了内容加速和安全防护的技术&…

二程运输的干散货船路径优化

在二程运输中&#xff0c;干散货船需要将货物从一个港口运输到多个不同的目的地港口。路径优化的目标是在满足货物运输需求、船舶航行限制等条件下&#xff0c;确定船舶的最佳航行路线&#xff0c;以最小化运输成本、运输时间或其他相关的优化目标。 影响因素 港口布局与距离…

Oracle物理恢复相关注意点

如果需要恢复的数据库或者数据文件不存在&#xff0c;则需要将全量备份集RESTORE[ 将全量备份集恢复到目标数据库中&#xff0c;称之为RESTORE。]到目标数据库中&#xff0c;然后再RECOVER[ 将增量备份集或者归档日志恢复到目标数据库中&#xff0c;称之为RECOVER。]增量备份集…

C++ string小记

#include<string> using std::string;string s1; string s2 "hello" //初始化一个hello字符串 string s3(5,a) //连续5个字符a组成的串&#xff0c;即aaaaa///字符串操作int length s1.size() //.size()求字符串长度char c1 s1[1]; //从下标0开始&#xf…

自然语言处理入门级项目——文本分类(预处理)

文章目录 前言1.数据预处理1.1数据集介绍1.2数据集抽取1.3划分数据集1.4数据清洗1.5数据保存 2.样本的向量化表征2.1词汇表2.2向量化2.3自定义数据集2.4备注 结语 前言 本篇博客主要介绍自然语言处理领域中一个项目案例——文本分类&#xff0c;具体而言就是判断评价属于积极还…

C++面试2——C与C++的关系

C与C++的关系及核心区别的解析 一、哲学与编程范式:代码组织的革命 过程式 vs 多范式混合 C语言是过程式编程的典范,以算法流程为中心,强调“怎么做”(How)。例如,实现链表操作需手动管理节点指针和内存。 C++则是多范式语言,支持面向对象(OOP)、泛型编程(模板)、函…

HTTP与HTTPS协议的核心区别

HTTP与HTTPS协议的核心区别 数据传输安全性 HTTP采用明文传输&#xff0c;数据易被窃听或篡改&#xff08;如登录密码、支付信息&#xff09;&#xff0c;而HTTPS通过SSL/TLS协议对传输内容加密&#xff0c;确保数据完整性并防止中间人攻击。例如&#xff0c;HTTPS会生成对称加…

PotPlayer 安装 madVR、LAV Filters 以提升解码能力和视频音频效果

PotPlayer自带的解码器并不是最好&#xff0c;如下两张截图都是出自 TOP GUN: Maverick 较暗、灰蒙蒙的一张&#xff0c;是安装插件之前明亮的一张&#xff0c;是安装插件之后 详细安装参考 https://www.bilibili.com/video/BV1UV5qzuE74?spm_id_from333.788.videopod.sectio…

深入理解 OpenCV 的 DNN 模块:从基础到实践

在计算机视觉领域蓬勃发展的当下&#xff0c;深度学习模型的广泛应用推动着技术的不断革新。OpenCV 作为一款强大且开源的计算机视觉库&#xff0c;其 DNN&#xff08;Deep Neural Network&#xff09;模块为深度学习模型的落地应用提供了高效便捷的解决方案。本文将以理论为核…

Spring MVC 中请求处理流程及核心组件解析

在 Spring MVC 中&#xff0c;请求从客户端发送到服务器后&#xff0c;需要经过一系列组件的处理才能最终到达具体的 Controller 方法。这个过程涉及多个核心组件和复杂的映射机制&#xff0c;下面详细解析其工作流程&#xff1a; 1. 核心组件与请求流程 Spring MVC 的请求处…

RISC-V 开发板 MUSE Pi Pro V2D图像加速器测试,踩坑介绍

视频讲解&#xff1a; RISC-V 开发板 MUSE Pi Pro V2D图像加速器测试&#xff0c;踩坑介绍 今天测试下V2D&#xff0c;这是K1特有的硬件级别的2D图像加速器&#xff0c;参考如下文档&#xff0c;但文档中描述的部分有不少问题&#xff0c;后面会讲下 https://bianbu-linux.spa…

hbase shell的常用命令

一、hbase shell的基础命令 # 版本号查看 [rootTest-Hadoop-NN-01 hbase]$ ./bin/hbase version HBase 2.4.0 Source code repository git://apurtell-ltm.internal.salesforce.com/Users/apurtell/src/hbase revision282ab70012ae843af54a6779543ff20acbcbb629# 客户端登录 […

深入解析Python中的Vector2d类:从基础实现到特殊方法的应用

引言 在Python面向对象编程中&#xff0c;特殊方法&#xff08;或称魔术方法&#xff09;是实现对象丰富行为的关键。本文将以Vector2d类为例&#xff0c;详细讲解如何通过特殊方法为自定义类添加多种表示形式和操作能力。 Vector2d类的基本行为 Vector2d类是一个二维向量类…

Zookeeper入门(三)

Zookeeper Java 客户端 项目构建 ookeeper 官方的客户端没有和服务端代码分离&#xff0c;他们为同一个jar 文件&#xff0c;所以我们直接引入 zookeeper的maven即可&#xff0c; 这里版本请保持与服务端版本一致&#xff0c;不然会有很多兼容性的问题 1 <dependency>…

Redis的主从架构

主从模式 全量同步 首先主从同步过程第一步 会先比较replication id 判断是否是第一次同步假设为第一次同步 那么就会 启动bgsave异步生成RDB 同时fork子进程记录生成期间的新数据发送RDB给从节点 清空本地数据写入RDB 增量同步 对比ReplicationID不同因此选择增量同步在Rep…

新电脑软件配置二:安装python,git, pycharm

安装python 地址 https://www.python.org/downloads/ 不是很懂为什么这么多版本 安装windows64位的 这里我是凭自己感觉装的了 然后cmd输入命令没有生效&#xff0c;先重启下&#xff1f; 重启之后再次验证 环境是成功的 之前是输入的python -version 命令输入错误 安装pyc…

docker 学习记录

docker pull nginx docker 将本地nginx快照保存到当前文件夹下 docker save -o nginx.tar nginx:latestdocker 将本地nginx 加载 docker load -i nginx.tar docker运行nginx在80端口 docker run --name dnginx -p 80:80 -d nginxredis启动 docker run --name mr -p 6379:6379 -…

什么是私有IP地址?如何判断是不是私有ip地址

在互联网的世界中&#xff0c;IP地址是设备之间通信的基础标识。无论是浏览网页、发送邮件还是在线游戏&#xff0c;IP地址都扮演着至关重要的角色。然而&#xff0c;并非所有的IP地址都是公开的&#xff0c;有些IP地址被保留用于内部网络&#xff0c;这就是我们所说的私有IP地…

功能安全管理

一、功能安全整体管理 1、功能安全文化&#xff0c;良好的功能安全文化包括&#xff1a; 1&#xff09; 在公司层面&#xff0c;有清晰的组织架构支撑功能安全开展 2&#xff09; 确保有足够的资源投入到功能安全开发中 3&#xff09; 有完整的功能安全培训 4&#xff09; 流程…

异常日志规范

目录 一、错误码 二、异常处理 三、日志规约 一、错误码 强制&#xff1a; 1、错误码的制订原则&#xff1a;快速溯源、沟通标准化。 1&#xff09;错误码必须能够快速知晓错误来源&#xff0c;可快速判断是谁的问题。 2&#xff09;错误码必须能够清晰地比对&#xff08;…