欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 健康 > 美食 > 使用itextpdf动态生成PDF

使用itextpdf动态生成PDF

2025/2/13 19:29:02 来源:https://blog.csdn.net/weixin_44006311/article/details/145567895  浏览:    关键词:使用itextpdf动态生成PDF

前言

在有些场景下我们可能需要根据指定的模板来生成 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、编写代码

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

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com