java利用pdfbox动态生成PDF

这篇具有很好参考价值的文章主要介绍了java利用pdfbox动态生成PDF。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Apache PDFBox 是一个用于处理 PDF 文档的 Java 库。它提供了许多功能和方法来读取、创建、操作和提取 PDF 文档的内容。

引入 maven 依赖

<!-- https://mvnrepository.com/artifact/org.apache.pdfbox/pdfbox -->
<dependency>
    <groupId>org.apache.pdfbox</groupId>
    <artifactId>pdfbox</artifactId>
    <version>2.0.24</version>
</dependency>

pdfbox 生成 pdf 实例

  try {
       // 创建一个空白的PDF文档
       PDDocument document = new PDDocument();
       // 创建一个页面
       PDPage page = new PDPage(PDRectangle.A4);
       document.addPage(page);
       // 创建一个内容流
       PDPageContentStream contentStream = new PDPageContentStream(document, page);
       // 设置字体和字号
       contentStream.setFont(PDType1Font.HELVETICA_BOLD, 12);
       // 在页面上绘制文本
       contentStream.beginText();
       contentStream.newLineAtOffset(100, 700);
       contentStream.showText("Hello, World!");
       contentStream.endText();
       // 关闭内容流
       contentStream.close();
       // 保存PDF文档
       document.save("output.pdf");
       // 关闭PDF文档
       document.close();
       System.out.println("PDF生成成功!");
   } catch (IOException e) {
       e.printStackTrace();
   }

常用方法

PDDocument 类

引用源码中对PDDocument 类的描述

This is the in-memory representation of the PDF document

这是PDF文档的内存表示,在 java 程序中,你可以简单理解为他就是 pdf 文档,后续对他的一系列操作就是对 pdf 文档的一系列操作。

创建全新的 pdf 文档:文档中无任何页面

PDDocument document=new PDDocument();

如果你想对原有的 pdf 模板进行动态数据的填充,可以使用PDDocument.load()方法来加载已经制作好的 pdf 模板,

PDDocument document = PDDocument.load(new ClassPathResource("/static/reportTemplate.pdf").getInputStream());

你也可以用文件形式来加载 pdf 模板,不过更推荐文件流的形式

PDDocument document = PDDocument.load(new ClassPathResource("/static/reportTemplate.pdf").getFile());

如果你想对你生成的 pdf 进行加密操作,你可以使用PDDocument load(InputStream input, String password)方法,如下设置了解密的密码为 123456.

PDDocument document = PDDocument.load(new ClassPathResource("/static/reportTemplate.pdf").getInputStream(),"123456");

PDDocument.load()中有好多重载的方法,这里就不一一列出。感兴趣的可以查看 pdfbox 的源码,

ByteArrayOutputStream baos = new ByteArrayOutputStream();;
document.save(baos); //保存文件到文件流

document.save("output.pdf"); //保存文件到文件

保存成文件流之后,有时候我们需要将文件传输到前端进行下载,

// 将PDF文件转换为字节数组
byte[] pdfBytes = baos.toByteArray();

// 创建InputStreamResource对象
ByteArrayInputStream bis = new ByteArrayInputStream(pdfBytes);
InputStreamResource resource = new InputStreamResource(bis);

// 设置HTTP响应头信息
HttpHeaders headers = new HttpHeaders();
       headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=output.pdf");
headers.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_PDF_VALUE);
// 返回带有PDF内容的响应实体
return ResponseEntity.ok()
       .headers(headers)
       .body(resource);

在对document 操作完成之后,一定要执行document.close()方法关闭 pdf 文档。

document.close();

PDPage 类

PDPage 属于 pdf 文档中的的页面,

int pageNumber=document.getNumberOfPages();

获取指定页面,

PDPage page = document.getPage(0);

如果你是对 pdf 模板进行操作,你可以通过document.getPage(index)方法来获取 pdf 文档的指定页面,并对其进行操作(index 从 0 开始)。你也可以通过new PDPage();创建一个全新的 page,

PDPage newPage = new PDPage(PDRectangle.A4);

如果我们是通过 new PDPage()的方式生成 page 页面时,我们需要将 page 页面添加到 pdf 文档中去(document),

document.addPage(newPage);

不过这种方式会将 page 添加到 pdf 文档的末尾,我们有时候需要将 page 添加到指定的位置,可以使用以下方法。

PDPage page=document.getPage(1); //获取第2页
PDPage newPage = new PDPage(PDRectangle.A4);
PDPageTree pages = document.getPages();
pages.insertAfter(newPage,page); //插入到第2页后面
pages.insertBefore(newPage,page); //插入到第2页前面

获取 page 页面总高度和总宽度,这个在后续的文字坐标定位中很有用,在 page 中原点坐标位于左下角,如果你想你的元素左边距为 10,上边距为 10,那么你的坐标将是(10,pageHeight-10)

float pageWidth = page.getMediaBox().getWidth();
float pageHeight = page.getMediaBox().getHeight();

PDPageContentStream

PDPageContentStream 类提供写入页面内容流的功能,它需要绑定 pdf 文档和指定的 page 页面,这样相当于创建了 page 当前页面的内容流。

PDPageContentStream contentStream = new PDPageContentStream(document, page);

如果不指定PDPageContentStream.AppendMode,默认会以重写模式执行,后续对 page 页面添加元素会覆盖现有页面内容流。

PDPageContentStream contentStream = new PDPageContentStream(document, page, PDPageContentStream.AppendMode.APPEND, true);

模式代码

模式

注释

PDPageContentStream.AppendMode.OVERWRITE

重写模式

覆盖现有页面内容流

PDPageContentStream.AppendMode.APPEND

追加模式

将内容流附加到所有现有页面内容流之后

PREPENDPDPageContentStream.AppendMode.

准备模式

在所有其他页面内容流之前插入

对contentStream 操作完成之后,需要关闭内容流。

contentStream.close();

pdf 写入内容

关于字体

在 Apache PDFBox 中,字体相关的类主要位于 org.apache.pdfbox.pdmodel.font 包下。下面是一些常用的字体类:

  1. PDType1Font:这个类表示 Type 1 字体,它是一种基于轮廓的字体格式。Type 1 字体常用于 PDF 文档中,如 Helvetica、Times Roman 和 Courier 等。

示例:

PDType1Font font = PDType1Font.HELVETICA_BOLD;
public static final PDType1Font TIMES_ROMAN = new PDType1Font("Times-Roman");
public static final PDType1Font TIMES_BOLD = new PDType1Font("Times-Bold");
public static final PDType1Font TIMES_ITALIC = new PDType1Font("Times-Italic");
public static final PDType1Font TIMES_BOLD_ITALIC = new PDType1Font("Times-BoldItalic");
public static final PDType1Font HELVETICA = new PDType1Font("Helvetica");
public static final PDType1Font HELVETICA_BOLD = new PDType1Font("Helvetica-Bold");
public static final PDType1Font HELVETICA_OBLIQUE = new PDType1Font("Helvetica-Oblique");
public static final PDType1Font HELVETICA_BOLD_OBLIQUE = new PDType1Font("Helvetica-BoldOblique");
public static final PDType1Font COURIER = new PDType1Font("Courier");
public static final PDType1Font COURIER_BOLD = new PDType1Font("Courier-Bold");
public static final PDType1Font COURIER_BOLD_OBLIQUE = new PDType1Font("Courier-BoldOblique");
public static final PDType1Font SYMBOL = new PDType1Font("Symbol");
public static final PDType1Font ZAPF_DINGBATS = new PDType1Font("ZapfDingbats");
  1. PDTrueTypeFont:这个类表示 TrueType 字体,也是一种基于轮廓的字体格式。TrueType 字体在 PDF 中也很常见。

PDTrueTypeFont font = PDType1Font.TIMES_ROMAN;
  1. PDType0Font:这个类表示 Type 0 字体,它是一种复合字体格式,可以包含多个子字体。Type 0 字体通常用于支持多语言和复杂字形需求,你可以使用它来加载自己自定义的字体文件。

PDType0Font font = PDType0Font.load(document, new ClassPathResource("/static/wryhRegular.ttf").getInputStream());
写入单行文本
contentStream.setFont(PDType1Font.COURIER_BOLD_OBLIQUE, 16);
contentStream.beginText();
contentStream.newLineAtOffset(50, pageHeight-50);
contentStream.showText("测试文本");
contentStream.endText();

在写入文本之前需要通过contentStream.setFont(PDFont font, float fontSize) 方法设置字体和字号,并通过beginText()方法开始一个新的文本段落,通过newLineAtOffset(x, y);方法设置文本的坐标位置,这里设置(50, pageHeight-50)表示文本位置位于左上角,离上面和左边 50 个单位。然后通过showText(String text)显示你需要展示的文本,最后用endText()方法结束文本段落。

连续写入多行文本
contentStream.setFont(PDType1Font.HELVETICA_BOLD, 12);

// 设置文本起始坐标
float startX = 50;
float startY = page.getMediaBox().getHeight() - 50;

// 设置行间距
float leading = 15;

// 写入多行文本
String[] lines = {
    "第一行文本",
    "第二行文本",
    "第三行文本"
};

contentStream.beginText();
contentStream.newLineAtOffset(startX, startY);

for (String line : lines) {
    contentStream.showText(line);
    contentStream.newLineAtOffset(0, -leading);
}

contentStream.endText();

写入多行文本和单行文本流程差不多,都需要先设置字体和字号,确定写入文字的坐标,不同的是,我们在 beginText()方法和endText()方法之间,多次执行了showText()和newLineAtOffset(),newLineAtOffset(0, -leading)方法代表着在上一行的位置基础上,X 轴不变,Y 轴向下移动leading 个单位。多次循环之后将多行文本添加到 pdf 文档中。

插入图片
PDImageXObject image = PDImageXObject.createFromFileByExtension(new File("path/to/image.jpg"), document);
float imageWidth = image.getWidth();
float imageHeight = image.getHeight();

PDPageContentStream contentStream = new PDPageContentStream(document, page);
contentStream.drawImage(image, x, y, imageWidth, imageHeight);

这里我们使用PDImageXObject.createFromFileByExtension()方法加载图片文件,创建一个PDImageXObject对象。确保将"path/to/image.jpg"替换为实际图片文件的路径,这里我将图片的宽度和高度设置为真实图片的宽高,在实际情况中你也可以自定义宽高,最后通过drawImage(image, x, y, imageWidth, imageHeight)方法将图片写入到 pdf 文档中,x,y 代表其 xy 坐标,后面的imageWidth, imageHeight 分别代表图片的宽度和高度。文章来源地址https://www.toymoban.com/news/detail-739412.html

添加矩形框
//设置边框颜色
contentStream.setStrokingColor(new Color(213, 213, 213));
//设置边框宽度为1
contentStream.setLineWidth(1);
// 添加矩形框到页面内容流
contentStream.addRect(50, pageHeight-50, 100, 100);
// 绘制矩形框的边框
contentStream.stroke();
//恢复原来的颜色,否则会影响文字颜色
contentStream.setStrokingColor(Color.BLACK);

文字坐标计算常用方法

    /**
     * 获取字体高度
     * */
    float getFontHeight(PDType0Font customFont,float fontSize){
        return customFont.getFontDescriptor().getFontBoundingBox().getHeight() / 1000 * fontSize;
    }
    /**
    * 计算文本宽度
    * */
    float getTextWidth(String text,float fontSize){
        return fontSize * text.length();
    }

附件

PDFBox官方文档(2.0.24)

到了这里,关于java利用pdfbox动态生成PDF的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Java使用pdfbox将pdf转图片

    目前比较主流的两种转pdf的方式,就是pdfbox和icepdf,两种我都尝试了下,icepdf解析出来有时候会出现中文显示不出来,网上的解决方式又特别麻烦,不是安装字体,就是重写底层类,所以我选择了pdfbox 在windows上好好的,x86_64的linux上也好好的,就是arm架构的linux上会出现 网上

    2024年02月10日
    浏览(59)
  • JAVA 实现PDF转图片(pdfbox版)

    依赖: pdf存放路径 正文开始: pdf转换多张图片、长图 展示效果: 附加:小程序预览wxml代码 依赖: pdf存放路径 正文开始: pdf转换多张图片、长图

    2024年02月06日
    浏览(58)
  • Java 利用Easyexcel动态导出表头列

    其中 fieldName 为要导出的字段名称 也就是 数据对象 中与之对应的字段名称 headName 为与字段对应的表头(我这里默认用的就是导出表头集合中字段排序就是导出的表头排序 如有需要,可以自己定义导出表头顺序) 导出util类,直接上代码 其中  CellStyle() 是设置的默认样式 

    2024年02月11日
    浏览(42)
  • Java使用pdfbox进行pdf和图片之间的转换

    pdfbox是Apache开源的一个项目,支持pdf文档操作功能。 官网地址: Apache PDFBox | A Java PDF Library 支持的功能如下图. 引入依赖

    2024年02月06日
    浏览(55)
  • 【Java】OpenPDF、iText、PDFBox 是三种常用的 PDF 处理库

    OpenPDF、iText、PDFBox 是三种常用的 PDF 处理库,它们各自具有独特的优势和特点,同时也存在一些局限性和差异。本文将对这四种库进行详细的比较,并通过代码示例来展示它们的使用。 1、OpenPDF OpenPDF 是一个用于创建和编辑 PDF 文档的 Java 库,它基于 iText 库的一个分支,提供

    2024年02月09日
    浏览(61)
  • java中pdfbox处理pdf常用方法(读取、写入、合并、拆分、写文字、写图片)

    方法代码: 测试用例: 2.1写文字 方法代码: 测试用例: A.pdf: A2.pdf: 2.2写图片 方法代码: 测试用例: A.pdf: pic.jpg: A2.pdf: 方法代码: 测试用例: 方法代码: 测试用例: 引用链接: (17条消息) 使用Apache PDFBox实现拆分、合并PDF_似有风中泣的博客-CSDN博客 (17条消息) Java使用P

    2024年02月11日
    浏览(128)
  • 如何通过Java的Apache PDFBox库制作一个PDF表格模板并填充数据

    要使用Java的Apache PDFBox库制作一个PDF表格模板并填充数据,你需要遵循以下步骤: 添加依赖 :首先,确保你的项目中包含了Apache PDFBox的依赖。如果你使用Maven,可以在你的 pom.xml 文件中添加以下依赖: 创建PDF模板 :你可以使用PDFBox创建一个简单的PDF模板,或者使用其他工具

    2024年02月22日
    浏览(59)
  • Java实现动态生成word报告

    1.准备好docx文件模板 举例:动态生成表格数据,以下是list数组类型的freemarker语法 将写好的word模板加入到templates目录下 2.在pom.xml中导入相关依赖 3.关于Minio的介绍 Minio 是一个开源的对象存储服务器,可用于存储和访问海量数据。以下是 Minio 的基本用法: (1)安装 Minio 首先

    2024年02月09日
    浏览(39)
  • java动态生成excel并且需要合并单元格

    java动态生成excel并且需要合并单元格 先上图看一下预期效果 集成poi 通过poi手动制作excel

    2024年02月13日
    浏览(42)
  • Java实现自动化pdf打水印小项目 使用技术pdfbox、Documents4j

    博主介绍:✌目前全网粉丝2W+,csdn博客专家、Java领域优质创作者,博客之星、阿里云平台优质作者、专注于Java后端技术领域。 涵盖技术内容:Java后端、算法、分布式微服务、中间件、前端、运维、ROS等。 博主所有博客文件目录索引:博客目录索引(持续更新) 视频平台:

    2024年02月20日
    浏览(73)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包