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

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;}

效果图

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

相关文章:

  • AD 多层线路及装配图PDF的输出
  • Springboot考研信息平台
  • LLM Text2SQL NL2SQL 实战总结
  • MongoDB数据库深度解析:架构、特性与应用场景
  • 呼叫中心高可用方案:全方位保障客服业务持续稳定
  • 7、MinIO服务器简介与安装
  • Python3 简易DNS服务器实现
  • Python机器学习笔记(二十三 模型评估与改进-网格搜索)
  • 20、工业协议转换与数据采集中间件 (模拟) - /数据与物联网组件/protocol-converter-middleware
  • 全球宠物经济新周期下的亚马逊跨境采购策略革新——宠物用品赛道成本优化三维路径
  • IP防护等级举例解析
  • 专项智能练习(加强题型)-DA-02
  • websocket入门详解
  • 【Ubuntu】安装BitComet种子下载器
  • 远程实时控制安卓模拟器技术scrcpy
  • 基于EtherCAT与ABP vNext 构建高可用、高性能的工业自动化平台
  • 软考 系统架构设计师系列知识点之杂项集萃(60)
  • Metagloves Pro+Manus Core:一套组合拳打通虚拟制作与现实工业的任督二脉
  • 【笔记】CosyVoice 模型下载小记:简单易懂的两种方法对比
  • Trae 插件 Builder 模式:从 0 到 1 开发天气查询小程序,解锁 AI 编程新体验
  • 商务部:长和集团出售港口交易各方不得规避审查
  • 体坛联播|C罗儿子完成国家队首秀,德约结束与穆雷合作
  • 上海杨浦:鼓励龙头企业与高校共建创新联合体,最高支持200万元
  • 加强战略矿产出口全链条管控工作部署会召开
  • “饿了么”枣庄一站点两名连襟骑手先后猝死,软件显示生前3天每日工作超11小时
  • 外交部:愿同拉美国家共同维护多边贸易体制