使用itextpdf动态生成PDF

server/2025/2/14 3:04:20/

前言

在有些场景下我们可能需要根据指定的模板来生成 PDF,比如说合同、收据、发票等等。因为 PDF 是不可编辑的,所以用代码直接对 PDF 文件进行修改是很不方便的,这里我是通过 itextAdobe Acrobat 来实现的,以下就是具体实现方法。

一、准备模板

Adobe Acrobat 是由 Adobe 公司开发的一款 PDF(Portable Document Format,便携式文档格式)编辑软件。借助它,你可以以 PDF 格式制作和保存文档 ,以便于浏览和打印,或使用更高级的功能。

说白一点就是 Adobe Acrobat 可以让你的 PDF 文件编程可编辑文件,PDF 文件可编辑的话,使用代码去修改就会方便很多。

adobe 中文官网:https://www.adobe.com/cn/

Adobe Acrobat 中文官网:https://www.adobe.com/cn/acrobat.html

如果你之前没有使用过这个软件,可以在上面我提供的官网里面去下载
在这里插入图片描述

下载完,打开该软件大概是这个样子的
在这里插入图片描述

2、创建模板
  • 使用Adobe编辑打开
    在这里插入图片描述
  • 点击准备表单,会自动帮你创建好表单,要是没有这个按钮,就去 更多工具 里添加
    在这里插入图片描述
  • 此按钮可以用户自定义添加表单
    在这里插入图片描述

3、引入依赖

		<dependencies><!-- https://mvnrepository.com/artifact/com.itextpdf/itextpdf --><dependency><groupId>com.itextpdf</groupId><artifactId>itextpdf</artifactId><version>5.5.13</version></dependency><!-- https://mvnrepository.com/artifact/com.itextpdf/itext-asian --><!--字体集--><dependency><groupId>com.itextpdf</groupId><artifactId>itext-asian</artifactId><version>5.2.0</version></dependency><dependency><groupId>org.apache.pdfbox</groupId><artifactId>pdfbox</artifactId><version>2.0.27</version></dependency><dependency><groupId>org.apache.pdfbox</groupId><artifactId>pdfbox-tools</artifactId><version>2.0.27</version></dependency></dependencies>

4、编写代码

java">package com.hnys.zhct.common.core.utils;import com.hnys.zhct.common.core.domain.ProblemSolutionVO;
import com.itextpdf.text.BaseColor;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Image;
import com.itextpdf.text.pdf.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.PDFRenderer;import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.List;
import java.util.Map;/*** 生成pdf的工具类** @author Simon*/
@Slf4j
public class GeneratedPdfUtils {public static void main(String[] args) {try {// 示例数据Map<String, Object> data = new HashMap<>();data.put("name", "lily");data.put("address", "麓谷");data.put("city", "changsha");data.put("state", "CN");data.put("zip", "123");// 例如:黑体字体String fontPath = "D:\\testImg\\myf\\simhei.ttf";// PDF文件路径String templatePath = "D:\\testImg\\template\\template.pdf", pdfPath = "D:\\output.pdf";// 水印内容String watermarkText = "国铁集团";// 生成PDFgeneratePdf(templatePath, pdfPath, data, fontPath, watermarkText);log.info("PDF生成成功!");// 输出目录String outputDir = "D:\\output_images";// 分辨率(DPI)通常300 DPI适用于高质量的图片,值越高质量越好,文件大小越大int dpi = 300;// 转换为PNG图片String imagePath = convertPdfToSingleLongPng(pdfPath, outputDir, dpi);// 打印生成的图片路径System.out.println("生成的图片: " + imagePath);} catch (IOException | DocumentException e) {log.error("PDF生成失败!");e.printStackTrace();}}/*** 通过PDF模板生成PDF文件** @param templatePath PDF模板路径* @param outputPath   生成的PDF文件路径* @param data         要填充的数据,键为表单字段名,值为要填充的内容* @param fontPath 字体* @param watermarkText 水印文字* @throws IOException 文件流异常* @throws DocumentException 文件读取异常*/@SuppressWarnings("unchecked")public static void generatePdf(String templatePath, String outputPath, Map<String,Object> data, String fontPath, String watermarkText)throws IOException, DocumentException {// 读取PDF模板PdfReader reader = new PdfReader(templatePath);// 创建PdfStamper对象PdfStamper stamper = new PdfStamper(reader, Files.newOutputStream(Paths.get(outputPath)));// 获取表单字段AcroFields form = stamper.getAcroFields();// 加载字体BaseFont baseFont = BaseFont.createFont(fontPath, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);// 设置表单字段的字体for (String fieldName : form.getFields().keySet()) {form.setFieldProperty(fieldName, "textfont", baseFont, null);}// 填充固定表单字段for (Map.Entry<String, Object> entry : data.entrySet()) {String fieldName = entry.getKey();Object value = entry.getValue();if (!(value instanceof List)) {form.setField(fieldName, value.toString());}}// 处理动态的List数据List<ProblemSolutionVO> problemSolutions = (List<ProblemSolutionVO>) data.get("problemList");if (CollectionUtils.isNotEmpty(problemSolutions)) {PdfContentByte content = stamper.getOverContent(1);float startY = 700; // 起始纵坐标float margin = 20;  // 间距for (ProblemSolutionVO ps : problemSolutions) {// 添加问题描述段落;如果存在其他string类型的字段,copy以下这段代码即可,需要多次执行main方法来调整坐标位置content.beginText();content.setFontAndSize(baseFont, 12);content.setTextMatrix(50, startY);content.showText(ps.getProblemDescription());content.endText();startY -= 20;// 添加图片Image image = Image.getInstance(ps.getImagePath());float width = 300;float height = width * image.getHeight() / image.getWidth();image.scaleToFit(width, height);image.setAbsolutePosition(50, startY - height);content.addImage(image);startY -= height + margin;}}// 设置表单为不可编辑stamper.setFormFlattening(true);// 添加水印int totalPages = reader.getNumberOfPages();for (int i = 1; i <= totalPages; i++) {PdfContentByte watermarkContent = stamper.getOverContent(i);watermarkContent.saveState();watermarkContent.setFontAndSize(baseFont, 50);watermarkContent.setColorFill(BaseColor.LIGHT_GRAY);watermarkContent.setTextMatrix(300, 300);watermarkContent.showTextAligned(Element.ALIGN_CENTER, watermarkText, 300, 300, 45);watermarkContent.restoreState();}// 关闭PdfStamperstamper.close();reader.close();}/*** 将PDF文件转换为单个长PNG图片** @param pdfPath  PDF文件路径* @param outputDir 输出图片的目录* @param dpi      图片分辨率(每英寸点数)* @return 生成的长图文件路径* @throws IOException 文件流异常*/public static String convertPdfToSingleLongPng(String pdfPath, String outputDir, int dpi) throws IOException {// 加载PDF文件PDDocument document = PDDocument.load(new File(pdfPath));PDFRenderer renderer = new PDFRenderer(document);// 创建输出目录(如果不存在)File outputDirFile = new File(outputDir);if (!outputDirFile.exists()) {outputDirFile.mkdirs();}// 获取PDF页数int pageCount = document.getNumberOfPages();// 逐页渲染为图片并计算总高度int totalHeight = 0;int width = 0;// 多页pdf即多张图片BufferedImage[] images = new BufferedImage[pageCount];for (int i = 0; i < pageCount; i++) {BufferedImage image = renderer.renderImageWithDPI(i, dpi);images[i] = image;totalHeight += image.getHeight();width = Math.max(width, image.getWidth());}// 创建一个新的长图BufferedImage longImage = new BufferedImage(width, totalHeight, BufferedImage.TYPE_INT_RGB);Graphics2D g2d = longImage.createGraphics();g2d.setColor(Color.WHITE);g2d.fillRect(0, 0, width, totalHeight);// 将所有图片合并到长图中int y = 0;for (BufferedImage image : images) {g2d.drawImage(image, 0, y, null);y += image.getHeight();}g2d.dispose();// 保存长图String longImagePath = outputDir + "/long_image.png";ImageIO.write(longImage, "png", new File(longImagePath));// 关闭PDF文档document.close();return longImagePath;}}

http://www.ppmy.cn/server/167504.html

相关文章

KVM虚拟化快速入门,最佳的开源可商用虚拟化平台

引言 在信息技术飞速发展的时代&#xff0c;服务器资源的高效利用成为企业关注的焦点。KVM 虚拟化作为一种先进的虚拟化技术&#xff0c;在众多虚拟化方案中脱颖而出&#xff0c;为企业实现服务器资源的优化配置提供了有效途径。 以往&#xff0c;物理服务器的资源利用效率较…

[MySQL]3-MySQL查询性能优化

目录 &#x1f31f;慢查询基础&#xff1a;优化数据访问 不必要的数据 MySQL扫描额外的记录 访问类型 重构查询的方式 切分查询&#xff08;分治&#xff09; 分解联接查询 特定类型查询优化 优化count查询 使用近似值 覆盖索引 优化LIMIT和OFFSET 使用覆盖索引的…

MySQL 安装配置(完整教程)

文章目录 一、MySQL 简介二、下载 MySQL三、安装 MySQL四、配置环境变量五、配置 MySQL 5.1 初始化 MySQL5.2 启动 MySQL 服务 六、修改 MySQL 密码七、卸载 MySQL八、结语 一、MySQL 简介 MySQL 是一款广泛使用的开源关系型数据库管理系统&#xff08;RDBMS&#xff09;&am…

docker发布自己的镜像

官方node-red镜像&#xff1a; nodered/node-red - Docker Image 拉取v3版本&#xff1a; docker pull nodered/node-red:3.1.14 运行镜像&#xff1a; docker run --restartalways --privilegedtrue -d -p 1880:1880 -v node_red_data:/data --name mynodered nodered/n…

【Android开发】安卓手机APP使用机器学习进行QR二维码识别

前言:本项目是一个 Android 平台的二维码扫描应用,具备二维码扫描和信息展示功能。借助 AndroidX CameraX 库实现相机的预览、图像捕获与分析,使用 Google ML Kit 进行二维码识别。为方便大家了解项目全貌,以下将介绍项目核心代码文件 MainActivity.java 和 AndroidManifes…

标题:深入探索 gRPC:后端开发中高效通信的利器

随着微服务架构在后端开发中的普及&#xff0c;如何实现服务之间高效、低延迟的通信成为了一个关键问题。传统的 HTTP 协议在处理大量并发请求时&#xff0c;虽然易于实现&#xff0c;但性能上存在一定的瓶颈。为了解决这个问题&#xff0c;gRPC&#xff08;Google Remote Proc…

MacOS安装Milvus向量数据库

Milvus 是一个高性能、高度可扩展的矢量数据库&#xff0c;可在从笔记本电脑到大规模分布式系统的各种环境中高效运行。Milvus 提供强大的数据建模功能&#xff0c;使您能够将非结构化或多模态数据组织成结构化集合。Milvus是Apache 2.0许可分发的开源项目。 Milvus 提供三种部…

Record-Mode 备案免关站插件,让 WordPress 备案不影响 SEO 和收录

专为 WordPress 网站设计的实用工具&#xff0c;旨在帮助网站在备案期间无需关闭即可正常收录所有页面的信息&#xff0c;利于SEO。 功能特性 免关站展示&#xff1a;开启插件后&#xff0c;非管理员用户访问网站时&#xff0c;会看到以半透明遮罩层或不透明全屏遮罩样式呈现的…