如何在Java中使用pdfbox,进行生成pdf操作,如文本居中,数据二列显示及图片显示?

pdfbox的基本使用

1. 添加 PDFBox 依赖
首先,确保你的项目中已经添加了 PDFBox 的 Maven 依赖。你可以使用类似以下的 Maven 依赖配置:

    <dependency>
      <groupId>org.apache.pdfbox</groupId>
      <artifactId>pdfbox</artifactId>
      <version>2.0.24</version> 
    </dependency>
    
    <dependency>
      <groupId>org.apache.pdfbox</groupId>
      <artifactId>pdfbox-tools</artifactId>
      <version>2.0.24</version> 
    </dependency>

2.创建pdf, 准备中文字体文件(如果你生成的pdf中没有中文可忽略)
为了支持中文字体,你需要有一个中文字体文件(如 .ttf 或 .otf 格式)。你可以从网络上下载常用的中文字体,如“微软雅黑”、“宋体”等。也可以使用本地字体,路径在C:\Windows\Fonts\下。

 // 创建一个页面并添加到文档中
    PDDocument document = new PDDocument();
    PDPage page = new PDPage(PDRectangle.A4);
    document.addPage(page);

   // 创建一个内容流以向页面添加内容
    PDPageContentStream contentStream = new PDPageContentStream(document, page);

3. 加载中文字体
在 Java 代码中,你需要使用 PDFBox 的 API 来加载中文字体。这通常涉及到使用 PDType0Font.load() 方法,该方法可以从文件中加载字体
案例:

 //加载加粗字体文件 
                PDType0Font jcload = PDType0Font.load(document, new FileInputStream("C:\\Windows\\Fonts\\SimHei.ttf"));
//加载常规字体文件 
                PDType0Font cgload = PDType0Font.load(document, new FileInputStream("C:\\Windows\\Fonts\\SimKai.ttf"));
                

4. 文本居中显示
在制作pdf的过程中文本居中显示是常见的如标题,首先我们要知道写入文本的高度和宽度,然后再计算出显示在pdf上的起始位置,x的值和y值。
案例:

//                pdf的长,宽
                float pageWidth = page.getMediaBox().getWidth();
                float pageHeight = page.getMediaBox().getHeight();
//                标题本身的长,宽
                String title = "中国****有限公司上海分公司****";
                //PDType0Font中的方法实现,其中fontSize是字体大小
                int fontSize = 18;
                float titleWidth = jcload.getStringWidth(title) / 1000 * fontSize;
                float titleHeight = jcload.getFontDescriptor().getFontBoundingBox().getHeight() / 1000 * fontSize;
//上边距
                int marginTop = 70;
                //居中的起始x值
                float startX = (pageWidth - titleWidth) / 2;
                //居中的起始Y值
                float startY = pageHeight - marginTop - titleHeight;
                //设置字体和大小
                 contentStream.setFont(jcload, fontSize);
                 contentStream.beginText();
//居中显示
                contentStream.newLineAtOffset(startX, startY);
                contentStream.showText(title);
                contentStream.endText();

4. 数据二列显示
在制作pdf的过程中文本显示为二列也是常见的如基本信息,首先我们要计算出显示在pdf上的每列宽带及它们的起始位置,x的值和y值,然后再设置好行间距。
案例:

//计算列宽
                float columnWidth = pageWidth / 2 - 10; // 假设有10点的间距
// 从页面顶部开始或者pdf上文Y的位置开始,这里是距离上文30行距的位置开始,实际使用可以根据需求自定义。
                float yPosition = startY - 30; 
                // 行间距
                float leading = 20; 

                // 假设我们有账单信息
                String[] items = {
                        "客户名称: 张三",
                        "账单月份: 03月",
                        "客户账单地址: 上海市徐汇区*********室",
                        "账单周期: 2024年03月01日至2024年03月31日",
                        "客户装机地址: 上海市徐汇区*********室",
                        "最后付款日期: 2024年04月01日",
                        "设备号: 180*****893",
                        "打印日期: 2024年04月05日"
                };
                //标记一下第一列
                int currentColumn = 1;
//                // 写入账单项
                for (int i = 0; i < items.length; i++) {
                //第一列开始X值为10
                    float xPosition = (currentColumn == 1) ? 10 : pageWidth - columnWidth - 10;
                    contentStream.beginText();
                    contentStream.setFont(cgload, 10);
                    contentStream.newLineAtOffset(xPosition, yPosition);
                    contentStream.showText(items[i]);
                    contentStream.endText();
                    //这里是判断是否是最后一个值,避免报异常
                    if(i != items.length -1){
                        contentStream.beginText();
                        contentStream.setFont(cgload, 10);
                        //第二列开始的X值为页宽-列宽-间距,Y值不变
                        contentStream.newLineAtOffset(pageWidth - columnWidth - 10, yPosition);
                        contentStream.showText(items[i+1]);
                        i++;
                        contentStream.endText();
                    }
                    //计算第二行的Y值
                    yPosition -= leading;
                }

5. 图片显示
在 Java 代码中,你需要使用 PDFBox 的 API 来加载中文字体。这通常涉及到使用 PDImageXObject.createFromFile() 方法,该方法可以操作图片
案例:

//                加载图片 这里使用的是本地地址图片名为5g.png
String tp5 = "C:\\Desktop\\202406\\0604\\5g.png";
PDImageXObject imageXObject = PDImageXObject.createFromFile(tp, document);
//画图片 X值是10,Y值是页高-100,图片的宽度是90,图片的高度是30,这里根据实际情况自定义
  contentStream.drawImage(imageXObject,10,pageHeight-100,90,30);

6. 最后保存pdf文档,不要忘记关闭流

          //写入完成记得关闭
  contentStream.close();
    document.close();
  // 保存文档bill为忘记名,可自定义
            document.save("bill.pdf");
  

整体效果图附上一张!!!
在这里插入图片描述

PDFBox 可以提取 PDF 文件文本内容,因此可以使用 PDFBox 识别 PDF 标题。以下是使用 PDFBox 提取 PDF 标题的示例代码: ```java import java.io.File; import java.io.IOException; import java.util.List; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.text.PDFTextStripper; import org.apache.pdfbox.text.TextPosition; public class PdfTitleRecognizer { public static void main(String[] args) throws IOException { PDDocument document = PDDocument.load(new File("example.pdf")); PDFTextStripper stripper = new PDFTextStripper() { @Override protected void writeString(String str, List<TextPosition> textPositions) throws IOException { // 检测标题 if (isTitle(textPositions)) { System.out.println(str.trim()); } super.writeString(str, textPositions); } }; stripper.setSortByPosition(true); stripper.setStartPage(1); stripper.setEndPage(document.getNumberOfPages()); stripper.getText(document); document.close(); } private static boolean isTitle(List<TextPosition> textPositions) { // 检测标题的规则 // 例如:第一行文本,字号大于等于18,加粗字体,居中对齐 if (textPositions.size() < 1) { return false; } TextPosition first = textPositions.get(0); if (first.getFontSizeInPt() < 18 || !first.getFont().getName().endsWith("Bold")) { return false; } float xMax = Float.MIN_VALUE, xMin = Float.MAX_VALUE, yMax = Float.MIN_VALUE; for (TextPosition pos : textPositions) { xMax = Math.max(xMax, pos.getXDirAdj() + pos.getWidthDirAdj()); xMin = Math.min(xMin, pos.getXDirAdj()); yMax = Math.max(yMax, pos.getYDirAdj() + pos.getHeightDir()); } float xMid = (xMax + xMin) / 2; if (Math.abs(first.getXDirAdj() + first.getWidthDirAdj() / 2 - xMid) > 5) { return false; } float yMid = yMax - first.getFontSizeInPt() / 2 - 5; for (TextPosition pos : textPositions) { if (Math.abs(pos.getYDirAdj() + pos.getHeightDir() / 2 - yMid) > 5) { return false; } } return true; } } ``` 这段代码首先加载 PDF 文档,然后使用 `PDFTextStripper` 类提取文本内容。在 `writeString` 方法,检测文本是否符合标题的规则,然后输出符合规则的文本。检测标题的规则可以根据具体的 PDF 文件格式和布局进行设置。在本例,检测规则为:第一行文本,字号大于等于 18,加粗字体,居中对齐。 注意,PDF 文件的标题可能分为多行,因此需要在 `writeString` 方法检测多行文本。也可以将检测规则修改为检测第一行和第二行文本的格式,以适应多行标题的情况。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值