PdfBox使用-创建PDF

标签: java

PDF(Portable Document Format的简称,意为“便携式文档格式”)

1、Java PDF开源库

名称

描述

优缺点

iText

iText是一个能够快速产生PDF文件的java类库。iText的java类对于那些要产生包含文本,表格,图形的只读文档是很有用的。它的类库尤其与java Servlet有很好的给合。使用iText与PDF能够使你正确的控制Servlet的输出。

Api使用简单,官网提供的资料很多

许可协议:APGL

简单说:就是商业用途要收费

PDF Box

PDFBox是一个Apache开源的x项目。可以操作PDF文档的Java PDF类库。它可以创建一个新PDF文档,操作现有PDF文档并提取文档中的内容。

文档少,表格不支持,api相对比较底层Apache License v2.0

免费使用,基本没有限制

FOP

FOP是由James Tauber发起的一个开源项目,原先的版本是利用xsl-fo将xml文件转换成pdf文件。但最新的版本它可以将xml文件转换成pdf,mif,pcl,txt等多种格式以及直接输出到打印机,并且支持使用SVG描述图形

本人没使用过,不很清楚

 

为什么使用Pdfbox?

1)使用没有限制

2)基本的pdf操作都满足

3)学习啊,学习啊

2、简单使用

要使用一个Java库,当然是先查看官网文档。

比较悲剧的是,pdfbox官网的资料很少,仅仅有功能特性的介绍。但是有一些使用案例:可以github上下载查看(https://github.com/apache/pdfbox)

依赖Jar(有这一个就够了哈,当然你也可以按需导入你需要的,pdfbox(核心)、fontbox、pdfbox-tools、pdfbox-debugger、xmpbox、preflight)

<dependency>
    <groupId>org.apache.pdfbox</groupId>
    <artifactId>pdfbox-app</artifactId>
    <version>2.0.18</version>
</dependency>

输出一行文本(其他的基本操作可以参考https://iowiki.com/pdfbox/pdfbox_quick_guide.html

public void createPdf() throws IOException {
    PDDocument document = new PDDocument();
    PDPage page = new PDPage(PDRectangle.A4);
    document.addPage(page);
    try (PDPageContentStream contentStream = new PDPageContentStream(document, page)) {
      contentStream.beginText();
      contentStream.newLineAtOffset(200, 700);
      contentStream.setFont(PDType1Font.TIMES_ROMAN, 12.5f);
      contentStream.showText("Hello PdfBox");
      contentStream.endText();
    }
    document.save("target/pdfboxtest.pdf");
    document.close();
}

 

3、坐标系

介绍

平面直接坐标系,其中横轴为X轴,纵轴为Y轴。简称直角坐标系。分为第一象限,第二象限,第三象限,第四象限。从右上角开始数起,逆时针方向算起。

x的正方向是水平相右,y的正方向是垂直相上(没有旋转的页面)

PdfBox的坐标系统,也就是你能看到的部分在【第一象限】视图,x值从左到右增加,y从下到上增加。

因此,如果您使用new PDPage()或new PDPage(PDPage.PAGE_SIZE_*)创建页面,则坐标系的原点将从页面的左下角开始。

坐标:旋转、原点移动

http://www.voidcn.com/article/p-pfgyxuyl-btn.html

4、文本测量

PDRectangle mediaBox = page.getMediaBox();
PDRectangle cropBox = page.getCropBox();
System.out.println("页面的高度:" + mediaBox.getHeight());
System.out.println("页面的宽度:" + mediaBox.getWidth());
//字体的高度
float fontCapHeight = font.getFontDescriptor().getCapHeight() / 1000f * fontSize;
//文字的宽度
float textWidth = font.getStringWidth(text);

5、画表格

PDDocument document = new PDDocument();
PDPage page = new PDPage(PDRectangle.A4);
document.addPage(page);
try (PDPageContentStream contentStream = new PDPageContentStream(document, page, PDPageContentStream.AppendMode.APPEND, true, true)) {
  float x = 30f;
  float y = page.getMediaBox().getUpperRightY() - 30f;
  //3行4列的表格
  int rows = 3;
  int cols = 4;
  //行高
  float rowHeight = 15.0f;
  float colWidth = 40.0f;
  contentStream.saveGraphicsState();
  //线条颜色
  contentStream.setStrokingColor(Color.RED);
  //线条宽度
  contentStream.setLineWidth(1.0f);
  //drawTable
  for (int row = 0; row <= rows; row++) {
    float xStart = x;
    float yStart = y - row * rowHeight;
    float xEnd = xStart + cols * colWidth;
    float yEnd = yStart;
    contentStream.moveTo(xStart, yStart);
    contentStream.lineTo(xEnd, yEnd);
  }
  for (int col = 0; col <= cols; col++) {
    float xStart = x + col * colWidth;
    float yStart = y;
    float xEnd = xStart;
    float yEnd = yStart - rows * rowHeight;
    contentStream.moveTo(xStart, yStart);
    contentStream.lineTo(xEnd, yEnd);
  }
  contentStream.stroke();
  contentStream.restoreGraphicsState();
}
document.save("target/pdfboxtest.pdf");
document.close();

6、easytable

github: https://github.com/vandeseer/easytable

//引入easytable Jar
<dependency>
   <groupId>com.github.vandeseer</groupId>
   <artifactId>easytable</artifactId>
   <version>0.6.0</version>
</dependency>
//3行4列的表格
PDDocument document = new PDDocument();
PDPage page = new PDPage(PDRectangle.A4);
document.addPage(page);
try (PDPageContentStream contentStream = new PDPageContentStream(document, page, PDPageContentStream.AppendMode.APPEND, true, true)) {
  PDFont font = PDType1Font.TIMES_ROMAN;
  float fontSize = 12.5f;
  Settings settings = Settings.builder()
    .font(font)
    .fontSize((int) fontSize)
    .horizontalAlignment(HorizontalAlignment.CENTER)
    .verticalAlignment(VerticalAlignment.MIDDLE)
    .backgroundColor(Color.WHITE)
    .wordBreak(true)
    .build();
  // Build the table
  //3行4列的表格
  int rows = 3;
  int cols = 4;
  float colWidth = 40.0f;
  Table.TableBuilder tableBuilder = Table.builder().borderColor(Color.RED).wordBreak(true);
  for (int col = 0; col < cols; col++) {
    tableBuilder.addColumnOfWidth(colWidth);
  }
  for (int row = 0; row < rows; row++) {
    Row.RowBuilder rowBuilder = Row.builder().wordBreak(true);
    for (int col = 0; col < cols; col++) {
      String colData = "text:" + col;
      rowBuilder.add(TextCell.builder().settings(settings).text(colData).borderWidth(0.5f).build());
    }
    tableBuilder.addRow(rowBuilder.build());
  }

  Table myTable = tableBuilder.build();
  float tableHeight = myTable.getHeight();
  System.out.println("表格高度:" + tableHeight);
  // Set up the drawer
  float x = 30f;
  float y = page.getMediaBox().getUpperRightY() - 30f;
  TableDrawer tableDrawer = TableDrawer.builder()
    .contentStream(contentStream)
    .startX(x)
    .startY(y)
    .table(myTable)
    .build();
  // And go for it!
  tableDrawer.draw();
  contentStream.restoreGraphicsState();
}
document.save("target/pdfboxtest.pdf");
document.close();

7、字体支持

字体下载网站: http://font.chinaz.com/

思源字体:思源黑体是Adobe与Google宣布推出的一款开源字体

NotoSansCJKtc字体:Google 开发的思源黑体,noto是谷歌取的名字,sans思源,cjk表示中文、日文、韩文,tc是中文繁体

PdfBox加载字体

  • SDK自带
PDType1Font.TIMES_ROMAN
  • 加载ttf字体
PDDocument document = new PDDocument();
InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(fontPath);
//第一种
PDFont font = PDType0Font.load(document, inputStream)
//第二种
TrueTypeFont ttfFont = new TTFParser().parse(inputStream);
PDFont font = PDType0Font.load(document, ttfFont, true)
  • 加载otf字体
PDDocument document = new PDDocument();
InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(fontPath);
//只能这样加载
OpenTypeFont otfFont = new OTFParser(false, true).parse(inputStream);
PDFont font = PDType0Font.load(this.getDocument(), otfFont, false)

 

8、同时多种字体适应的解决方案

https://www.ojit.com/article/1798712

eg. 你好,Hello PdfBox,クーポン券手数料合計

        PDDocument document = new PDDocument();
        PDPage page = new PDPage(PDRectangle.A4);
        document.addPage(page);
        List<PDFont> fontList = new ArrayList<>();
        fontList.add(PDType1Font.TIMES_ROMAN);
        try (InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("fonts/NotoSansCJKtc-Regular.ttf")) {
            fontList.add(PDType0Font.load(document, inputStream));
        }
        String text = "你好,Hello PdfBox,クーポン券手数料合計";
        try (PDPageContentStream contentStream = new PDPageContentStream(document, page, PDPageContentStream.AppendMode.APPEND, true, true)) {
            int len = text.length();
            contentStream.beginText();
            contentStream.newLineAtOffset(200f, 200f);
            for (int i = 0; i < len; i++) {
                String s = String.valueOf(text.charAt(i));
                System.out.println(s);
                PDFont useFont = null;
                for (PDFont font : fontList) {
                    try {
                        font.encode(s);
                        useFont = font;
                    } catch (Exception e) {
                        //ignore
                        continue;
                    }
                }
                contentStream.setFont(useFont, 12f);
                contentStream.showText(s);
            }
            contentStream.endText();
        }
        document.save("target/pdfboxtest.pdf");
        document.close();

9、参考资料

10、使用案例

版权声明:本文为lsziri原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/lsziri/article/details/103969694

智能推荐

马拉车算法(Manacher's Algorithm)

这是悦乐书的第343次更新,第367篇原创 Manacher’s Algorithm,中文名叫马拉车算法,是一位名叫Manacher的人在1975年提出的一种算法,解决的问题是求最长回文子串,神奇之处在于将算法的时间复杂度精进到了O(N),下面我们来详细介绍下这个算法的思路。 01 算法由来 在求解最长回文子串的问题时,一般的思路是以当前字符为中心,向其左右两边扩展寻找回文,但是这种解...

HTML学习笔记--第一天

1界面基本结构 HTML存在有版本差异 HTML5的头部 其他版本 页面标签 meta标签 META元素通常用于指定网页的描述,关键词,文件的最后修改时间,作者及其他元数据。 元数据可以被使用浏览器(如何显示内容或重新加载页面),搜索引擎(关键词),或其他 Web 服务调用。 <h1>----<h6>标签 定义了六个不同级别的标题 <p></p>标签...

springcloud之熔断器hystrix及服务监控Dashboard

文章目录 一、服务雪崩效应 二、服务熔断服务降级 三、hystrix默认超时时间设置 四、hystrix服务监控dashboard 一、服务雪崩效应 当一个请求依赖多个服务的时候: 正常情况下的访问(图解) 但是,当请求的服务中出现无法访问、异常、超时等问题时(图中的I),那么用户的请求将会被阻塞。 如果多个用户的请求中,都存在无法访问的服务,那么他们都将陷入阻塞的状态中。 Hystrix的引入,...

使用for循环遍历文件、使用while循环遍历文件

使用for循环遍历文件 1、打开文件读 打开文件,从头到尾读完后,再执行read()就没有了 关闭后就不能读 readlines()和readline()区别: readline() :一行一行读取,返回字符串,当指针到文件末尾后,返回空 readlines():整个内容都输出,再输入,返回空 fd.next(): 和readline() 差不多,不过读完最后一行,返回报错 2、打开文件写 f =...

带权并查集_How Many Answers Are Wrong

这道题有点巧妙~ 大致题意:给定一个数组,每次给出l,r,value表示区间 [ l , r ] 的总和为value,但每次给出的value可能和前面的答案有冲突,求冲突次数。 举例:好比如前面给出了[1,10]的和为100、[1,7]的和为60,那么自然就可以确定[8,10]的和为100-60=40,但题目术输出却给出[8,10]的和为80,那么就和前面的答案冲突了。 这道题的突破点在于,可以以...

猜你喜欢

tcp/ip(1)

tcp/ip 1.网络编程中服务端接受请求套接字创建过程。 2.客户端套接字创建过程。 3.套接字类型与协议设置 4.地址族与数据序列 ip // Internet Protocol (网络协议) 端口 // 为区分程序中创建的套接字而分配给套接字的序号,可分配(0-65535), 0-1023为知名端口,不建议分配。 网络地址 // 1 ipv4 2 ipv6 它俩差别就是表示ip地址所用的字节...

支持在 Flutter 上构建视频通话应用的 plugin

Google 在去年12月正式发布了,跨平台开发框架 Flutter 1.0。一套代码,可在 Android、iOS 双端运行。 早在去年我们举办的1024活动的互动环节中,有开发者提出希望我们可以支持 Flutter。 于是,我们基于 Agora Video SDK 封装了一个 Flutter plugin,可以为你的 Flutter App 实现实时的音视频通话功能。 与此同时,我们也准备了一...

Linux下悟空crm安装

悟空CRM是一款开源的客户关系管理系统 ,采用PHP及JAVA架构。支持云服务SAAS服务,可为企业提供多种行业的CRM解决方案。 前提条件 你要保证你的Linux下安装了redis,mysql,tomcat,jdk 通过码云或github下载 wukongcrm-72crm-java-master.zip ,然后解压到指定目录:unzip wukongcrm-72crm-java-master....

数据压缩实验三:Huffman编解码

一、基本原理 1.Huffman编码算法 ()统计频率:将文件以ASCII字符流的形式读入,统计每个符号的发生频率; (2)排序:将所有文件中出现过的字符按照频率从小到大的顺序排列; (3)每一次选出最小的两个值,作为二叉树的两个叶子节点,将和作为它们的根节点,这两个叶子节点不再参与比较,新的根节点参与比较;重复此步骤,直到最后得到和为1的根节点; (4)编码:将形成的二叉树的左节点标0,右节点标...

Sublime text 添加到鼠标右键功能

以前安装一直都会有右键菜单,这次不知道怎么回事,竟然显示没有,后来试着查了查,然后就总结下来。 有两种方法,一种是直接修改注册列表,但是这样感觉略微麻烦。 所以,使用第二种方法更好。 打开安装路径,然后新建文本,写入 这里 是可执行文件的路径 然后将文件保存为sublime_addright.reg ,之后打开运行,即可。...