springboot基础(79):通过pdf模板生成文件

文章目录

  • 前言
  • 通过pdf模板生成文件
    • 一 . 制作模板
    • 二、编辑代码实现模板生成pdf文件
    • 三、pdf在线预览和文件下载
  • 扩展问题
  • 遇到的问题
    • 1. 更换字体为宋体常规
    • 2. 下载时中文文件名乱码问题

前言

通过pdf模板生成文件。
支持文本,图片,勾选框。

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

本章代码已分享至Gitee: https://gitee.com/lengcz/pdfdemo01

通过pdf模板生成文件

一 . 制作模板

  1. 先使用wps软件制作一个docx文档
    在这里插入图片描述

  2. 将文件另存为pdf文件
    在这里插入图片描述

  3. 使用pdf编辑器,编辑表单,(例如福昕PDF阅读器、Adobe Acrobat DC)

不同的pdf编辑器使用方式不同,建议自行学习如何使用pdf编辑器编辑表单

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

  1. 将修改后的文件保存为template1.pdf文件。

二、编辑代码实现模板生成pdf文件

  1. 引入依赖
 <dependency><groupId>com.itextpdf</groupId><artifactId>itextpdf</artifactId><version>5.5.13.3</version></dependency>
  1. 编写pdf工具类和相关工具
package com.it2.pdfdemo01.util;import com.itextpdf.text.BadElementException;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Image;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.*;import java.io.*;
import java.util.List;
import java.util.Map;/*** pdf 工具*/
public class PdfUtil {/*** 通过pdf模板输出到流** @param templateFile 模板* @param dataMap      input数据* @param picData      image图片* @param checkboxMap  checkbox勾选框* @param outputStream 输出流*/public static void output(String templateFile, Map<String, Object> dataMap, Map<String, byte[]> picData, Map<String, String> checkboxMap, OutputStream outputStream) {OutputStream os = null;PdfStamper ps = null;PdfReader reader = null;try {reader = new PdfReader(templateFile);ps = new PdfStamper(reader, outputStream);AcroFields form = ps.getAcroFields();BaseFont bf = BaseFont.createFont("Font/SIMYOU.TTF", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);form.addSubstitutionFont(bf);if (null != dataMap) {for (String key : dataMap.keySet()) {form.setField(key, dataMap.get(key).toString());}}ps.setFormFlattening(true);if (null != checkboxMap) {for (String key : checkboxMap.keySet()) {form.setField(key, checkboxMap.get(key), true);}}PdfStamper stamper = ps;if (null != picData) {picData.forEach((filedName, imgSrc) -> {List<AcroFields.FieldPosition> fieldPositions = form.getFieldPositions(filedName);for (AcroFields.FieldPosition fieldPosition : fieldPositions) {int pageno = fieldPosition.page;Rectangle signrect = fieldPosition.position;float x = signrect.getLeft();float y = signrect.getBottom();byte[] byteArray = imgSrc;try {Image image = Image.getInstance(byteArray);PdfContentByte under = stamper.getOverContent(pageno);image.scaleToFit(signrect.getWidth(), signrect.getHeight());image.setAbsolutePosition(x, y);under.addImage(image);} catch (BadElementException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} catch (DocumentException e) {e.printStackTrace();}}});}} catch (Exception e) {e.printStackTrace();} finally {try {ps.close();reader.close();} catch (Exception e) {e.printStackTrace();}}}/*** 通过pdf模板输出到文件** @param templateFile 模板* @param dataMap      input数据* @param picData      image图片* @param checkboxMap  checkbox勾选框* @param outputFile   输出流*/public static void output(String templateFile, Map<String, Object> dataMap, Map<String, byte[]> picData, Map<String, String> checkboxMap, File outputFile) throws IOException {FileOutputStream fos = new FileOutputStream(outputFile);try {output(templateFile, dataMap, picData, checkboxMap, fos);} finally {fos.close();}}/*** 通过pdf模板输出到文件** @param templateFile 模板* @param dataMap      input数据* @param picData      image图片* @param checkboxMap  checkbox勾选框* @param filePath     路径* @param fileName     文件名*/public static void output(String templateFile, Map<String, Object> dataMap, Map<String, byte[]> picData, Map<String, String> checkboxMap, String filePath, String fileName) throws IOException {File file = new File(filePath + File.separator + fileName);output(templateFile, dataMap, picData, checkboxMap, file);}}
package com.it2.pdfdemo01.util;import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;/*** 图片工具*/
public class ImageUtil {/*** 通过图片路径获取byte数组** @param url 路径* @return*/public static byte[] imageToBytes(String url) {ByteArrayOutputStream byteOutput = new ByteArrayOutputStream();BufferedImage bufferedImage = null;try {bufferedImage = ImageIO.read(new File(url));ImageIO.write(bufferedImage, "jpg", byteOutput);return byteOutput.toByteArray();} catch (IOException e) {e.printStackTrace();} finally {try {if (byteOutput != null)byteOutput.close();} catch (IOException e) {e.printStackTrace();}}return null;}
}

用到的字体文件(幼圆常规,C盘Windows/Fonts目录下

在这里插入图片描述

  1. 测试用例并执行,生成了pdf文件。
 @Testpublic void testPdf() throws IOException {String templateFile = "D:\\test3\\template1.pdf";Map<String, Object> dataMap = new HashMap<>();dataMap.put("username", "王小鱼");dataMap.put("age", "11");dataMap.put("address", "深圳市宝安区和林大道");Map<String, byte[]> picMap = new HashMap<>();byte[] imageToBytes = ImageUtil.imageToBytes("D:\\test3\\dog3.png");picMap.put("head", imageToBytes);Map<String, String> checkboxMap = new HashMap<>();checkboxMap.put("apple", "Yes");checkboxMap.put("orange", "Yes");checkboxMap.put("peach", "No");PdfUtil.output(templateFile, dataMap, picMap, checkboxMap, "D:\\test3", "test1.pdf");System.out.println("-------通过模板生成文件结束-------");}

在这里插入图片描述

三、pdf在线预览和文件下载

package com.it2.pdfdemo01.controller;import com.it2.pdfdemo01.util.ImageUtil;
import com.it2.pdfdemo01.util.PdfUtil;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;@RestController
@RequestMapping("/pdftest")
public class MyPdfController {/*** 在线预览pdf** @param request* @param response* @throws IOException*/@GetMapping("/previewPdf")public void previewPdf(HttpServletRequest request, HttpServletResponse response) throws IOException {String templateFile = "D:\\test3\\template1.pdf";Map<String, Object> dataMap = new HashMap<>();dataMap.put("username", "王小鱼");dataMap.put("age", "11");dataMap.put("address", "深圳市宝安区和林大道");Map<String, byte[]> picMap = new HashMap<>();byte[] imageToBytes = ImageUtil.imageToBytes("D:\\test3\\dog3.png");picMap.put("head", imageToBytes);Map<String, String> checkboxMap = new HashMap<>();checkboxMap.put("apple", "Yes");checkboxMap.put("orange", "Yes");checkboxMap.put("peach", "No");response.setCharacterEncoding("utf-8");response.setContentType("application/pdf");String fileName = new String("测试预览pdf文件".getBytes(), "ISO-8859-1");//避免中文乱码response.setHeader("Content-Disposition", "inline;filename=".concat(String.valueOf(fileName) + ".pdf"));PdfUtil.output(templateFile, dataMap, picMap, checkboxMap, response.getOutputStream());}/*** 下载pdf** @param request* @param response* @throws IOException*/@GetMapping("/downloadPdf")public void downloadPdf(HttpServletRequest request, HttpServletResponse response) throws IOException {String templateFile = "D:\\test3\\template1.pdf";Map<String, Object> dataMap = new HashMap<>();dataMap.put("username", "王小鱼");dataMap.put("age", "11");dataMap.put("address", "深圳市宝安区和林大道");Map<String, byte[]> picMap = new HashMap<>();byte[] imageToBytes = ImageUtil.imageToBytes("D:\\test3\\dog3.png");picMap.put("head", imageToBytes);Map<String, String> checkboxMap = new HashMap<>();checkboxMap.put("apple", "Yes");checkboxMap.put("orange", "Yes");checkboxMap.put("peach", "No");response.setCharacterEncoding("utf-8");response.setContentType("application/pdf");String fileName = new String("测试预览pdf文件".getBytes(), "ISO-8859-1");//避免中文乱码response.setHeader("Content-Disposition", "attachment;filename=".concat(String.valueOf(fileName) + ".pdf"));PdfUtil.output(templateFile, dataMap, picMap, checkboxMap, response.getOutputStream());}
}

启动服务器测试

  • 预览,访问 http://localhost:8080/pdftest/previewPdf
    在这里插入图片描述
  • 下载 访问 http://localhost:8080/pdftest/downloadPdf
    在这里插入图片描述

预览和下载的区别,只有细微区别。
在这里插入图片描述

扩展问题

android手机浏览器不能在线预览pdf文件,pc浏览器和ios浏览器可以在线预览pdf文件。
解决方案请见: https://lengcz.blog.csdn.net/article/details/132604135

遇到的问题

1. 更换字体为宋体常规

在这里插入图片描述

只能是下面这种写法

//            BaseFont bf = BaseFont.createFont("Font/SIMYOU.TTF", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED); //幼圆常规String srcFilePath = PdfUtil.class.getResource("/")+ "Font/simsun.ttc"; //宋体常规String templatePath = srcFilePath.substring("file:/".length())+",0";BaseFont bf = BaseFont.createFont(templatePath, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);

2. 下载时中文文件名乱码问题

String fileName = new String("测试预览pdf文件".getBytes(), "ISO-8859-1");//避免中文乱码response.setHeader("Content-Disposition", "attachment;filename=".concat(String.valueOf(fileName) + ".pdf"));

点击下载
在这里插入图片描述

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

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

相关文章

17.Oauth2-微服务认证

1.Oauth2 OAuth 2.0授权框架支持第三方支持访问有限的HTTP服务&#xff0c;通过在资源所有者和HTTP服务之间进行一个批准交互来代表资源者去访问这些资源&#xff0c;或者通过允许第三方应用程序以自己的名义获取访问权限。 为了方便理解&#xff0c;可以想象OAuth2.0就是在用…

实现 Entity实例生命周期和vue组件生命周期融合

场景解决方案实现方案index.vue方案解决效果 场景 ceisum中Entity实例的生成和销毁&#xff0c;大部分逻辑和vue代码分离&#xff0c;导致不好阅读和维护 解决方案 ceisum 中实例 Entity 的生命周期&#xff0c;和vue的生命周期’相似’&#xff0c;把两个生命周期结合(把en…

Jmete+Grafana+Prometheus+Influxdb+Nginx+Docker架构搭建压测体系/监控体系/实时压测数据展示平台+遇到问题总结

背景 需要大批量压测时&#xff0c;单机发出的压力能力有限&#xff0c;需要多台jmeter来同时进行压测&#xff1b;发压机资源不够&#xff0c;被压测系统没到瓶颈之前&#xff0c;发压机难免先发生资源不足的情形&#xff1b;反复压测时候也需要在不同机器中启动压测脚本&…

比较opencv,pillow,matplotlib,skimage读取图像的速度比

上面这些库都被广泛用于图像处理和计算机视觉任务&#xff1b; 不同的图像读取库&#xff08;OpenCV&#xff0c;Pillow&#xff0c;matplotlib和skimage&#xff09;的读取速度&#xff0c;是怎么样的一个情况&#xff1f; 下面分别从读取速度&#xff0c;以及转换到RGB通道…

《虚拟仿真实验教学平台》三项团体标准启动会在 ALVA 举办

8 月 11 日&#xff0c;《虚拟仿真实验教学平台》三项团体标准启动会&#xff08;下以“启动会”简称&#xff09;以线下线上相结合的会议形式在 ALVA Systems 北京总部举办。 启动会上&#xff0c;ALVA 与专家组、编写组成员和企业代表围绕《虚拟仿真实验教学平台建设指南》、…

不同写法的性能差异

“ 达到相同目的,可以有多种写法,每种写法有性能、可读性方面的区别,本文旨在探讨不同写法之间的性能差异 len(str) vs str "" 本部分参考自: [问个 Go 问题&#xff0c;字符串 len 0 和 字符串 "" &#xff0c;有啥区别&#xff1f;](https://segmentf…

基础算法-递推算法-学习

现象&#xff1a; 基础算法-递推算法-学习 方法&#xff1a; 这就是一种递推的算法思想。递推思想的核心就是从已知条件出发&#xff0c;逐步推算出问题的解 最常见案例&#xff1a; 一&#xff1a;正向递推案例&#xff1a; 弹力球回弹问题&#xff1a; * 弹力球从100米高…

OpenLayers7官方文档翻译,OpenLayers7中文文档,OpenLayers快速入门

快速入门 这个入门文档向您展示如何放一张地图在web网页上。 开发设置使用 NodeJS&#xff08;至少需要Nodejs 14 或更高版本&#xff09;&#xff0c;并要求安装 git。 设置新项目 开始使用OpenLayers构建项目的最简单方法是运行&#xff1a;npm create ol-app npm create…

Go 面向对象(匿名字段)

概述 严格意义上说&#xff0c;GO语言中没有类(class)的概念,但是我们可以将结构体比作为类&#xff0c;因为在结构体中可以添加属性&#xff08;成员&#xff09;&#xff0c;方法&#xff08;函数&#xff09;。 面向对象编程的好处比较多&#xff0c;我们先来说一下“继承…

QWidget的ui界面绘制成图片

文章目录 源文件源码解释效果修复图片清晰度 源文件 #include "widget.h" #include "ui_widget.h"#include <QPixmap> #include <QDir>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);// 构造…

Pinely Round 2 (Div. 1 + Div. 2) G. Swaps(组合计数)

题目 给定一个长度为n(n<1e6)的序列&#xff0c;第i个数ai(1<ai<n)&#xff0c; 操作&#xff1a;你可以将当前i位置的数和a[i]位置的数交换 交换可以操作任意次&#xff0c;求所有本质不同的数组的数量&#xff0c;答案对1e97取模 思路来源 力扣群 潼神 心得 感…

Android之布局转圆角

Android之布局转圆角 文章目录 Android之布局转圆角说明一、效果图二、实现步骤1.自定义RoundRelativeLayout2.使用 总结 说明 很多需求比较无语&#xff0c;需要某个布局转圆角&#xff0c;像个显眼包一样&#xff0c;所以为了满足显眼包&#xff0c;必须整呐提示&#xff1a…

Java智慧工地信息化管理平台源码,依托计算机信息、网络通讯、物联网、系统集成及云计算技术建立

Java智慧工地源码 智慧工地APP源码 系统定义&#xff1a; 智慧工地信息化管理平台是依托计算机信息、网络通讯、物联网、系统集成及云计算技术&#xff0c;通过数据采集、信息动态交互、智能分析&#xff0c;建立起来的一套集成的项目建设综合管理系统。实现项目管理信息化、网…

LeetCode 剑指offer 09.用两个栈实现队列

LeetCode 剑指offer 09.用两个栈实现队列 题目描述 用两个栈实现一个队列。队列的声明如下&#xff0c;请实现它的两个函数 appendTail 和 deleteHead &#xff0c;分别完成在队列尾部插入整数和在队列头部删除整数的功能。(若队列中没有元素&#xff0c;deleteHead 操作返回…

C语言网络编程实现组播(多播)

1、组播IP划分 224.0.0.0&#xff5e;224.0.0.255 为预留的组播地址&#xff08;永久组地址&#xff09;&#xff0c;地址224.0.0.0保留不做分配&#xff0c;其它地址供路由协议使用&#xff1b; 224.0.1.0&#xff5e;224.0.1.255 是公用组播地址&#xff0c;可以用于Inter…

Scala的特质trait与java的interface接口的区别,以及Scala特质的自身类型和依赖注入

1. Scala的特质trait与java接口的区别 Scala中的特质&#xff08;trait&#xff09;和Java中的接口&#xff08;interface&#xff09;在概念和使用上有一些区别&#xff1a; 默认实现&#xff1a;在Java中&#xff0c;接口只能定义方法的签名&#xff0c;而没有默认实现。而在…

机器连接和边缘计算

以一种高效、可扩展的方式进行连接和边缘计算的结合&#xff0c;解决了在工业物联网应用中的机器数据集成问题。 一 边缘计算 边缘计算描述了由中央平台管理的数据分散式处理&#xff0c;它对于工业物联网而言非常重要。在许多应用程序中&#xff0c;由于数据量非常大&#xf…

【USRP】集成化仪器系列1 :信号源,基于labview实现

USRP 信号源 1、设备IP地址&#xff1a;默认为192.168.10.2&#xff0c;请勿 修改&#xff0c;运行阶段无法修改。 2、天线输出端口是TX1&#xff0c;请勿修改。 3、通道&#xff1a;0 对应RF A、1 对应 RF B&#xff0c;运行 阶段无法修改。 4、中心频率&#xff1a;当需要…

界面控件DevExpress .NET应用安全 Web API v23.1亮点:支持Swagger模式

DevExpress拥有.NET开发需要的所有平台控件&#xff0c;包含600多个UI控件、报表平台、DevExpress Dashboard eXpressApp 框架、适用于 Visual Studio的CodeRush等一系列辅助工具。 DevExpress 今年第一个重要版本v23.1日前已正式发布了&#xff0c;该版本拥有众多新产品和数十…

电子学会 2023年3月 青少年软件编程Python编程等级考试三级真题解析(选择题+判断题+编程题)

青少年编程Python编程等级考试三级真题解析(选择题+判断题+编程题) 2023年3月 一、选择题(共25题,共50分) 十进制数111转换成二进制数是?( ) A. 111 B. 1111011 C. 101111 D. 1101111 答案选:D 考点分析:考察python 进制转换 十进制转二进制,采用除二倒取余数,直到商…