0

0

使用iText生成PDF_html/css_WEB-ITnose

php中文网

php中文网

发布时间:2016-06-21 08:52:19

|

2505人浏览过

|

来源于php中文网

原创

itext的更新变化很大,早期版本在pdf样式上可能会有瑕疵,所有我使用的最新的5.5.6包

1.添加Maven依赖

itext核心包 和xmlworder字体包

      com.itextpdf     itextpdf     5.5.6
   com.itextpdf.tool   xmlworker   5.5.6

2. 直接生成pdf的方式,非常简单,用文字创建段落等即可,设置好字体、间距、对齐方式等等即可,弄个Hello World 的例子。

package com.thunisoft.demo;  import java.io.FileOutputStream;  import com.itextpdf.text.Document;  import com.itextpdf.text.Font;  import com.itextpdf.text.FontFactoryImp;  import com.itextpdf.text.PageSize;  import com.itextpdf.text.Paragraph;  import com.itextpdf.text.pdf.BaseFont;  import com.itextpdf.text.pdf.PdfPHeaderCell;  import com.itextpdf.text.pdf.PdfPTable;  import com.itextpdf.text.pdf.PdfWriter;     /**  * 创建一个简单pdf文档,文字、表格  *  * @author zhangwd  * @version 1.0  *  */  public class PdfDemo_1 {      private static void create() throws Exception {          // 创建一个文档(默认大小A4,边距36, 36, 36, 36)          Document document = new Document();          // 设置文档大小          document.setPageSize(PageSize.A4);          // 设置边距,单位都是像素,换算大约1厘米=28.33像素          document.setMargins(50, 50, 50, 50);             // 创建writer,通过writer将文档写入磁盘          PdfWriter writer = PdfWriter.getInstance(document,newFileOutputStream("c:/demo.1.pdf"));             // demo          String title = "凉州词";          String content = "黄河远上白云间,一片孤城万仞山。羌笛何须怨杨柳,春风不度玉门关。";             // 定义字体          FontFactoryImp ffi = new FontFactoryImp();          // 注册全部默认字体目录,windows会自动找fonts文件夹的,返回值为注册到了多少字体          ffi.registerDirectories();          // 获取字体,其实不用这么麻烦,后面有简单方法          Font font = ffi.getFont("宋体",BaseFont.IDENTITY_H,BaseFont.EMBEDDED, 12, Font.UNDEFINED, null);             // 打开文档,只有打开后才能往里面加东西          document.open();             // 设置作者          document.addAuthor("王之涣");          // 设置创建者          document.addCreator("王之涣");          // 设置主题          document.addSubject("测试");          // 设置标题          document.addTitle("凉州词");             // 增加一个段落          document.add(new Paragraph(title, font));          document.add(new Paragraph(content, font));          document.add(new Paragraph("\n\r", font));             // 创建表格,5列的表格          PdfPTable table = new PdfPTable(4);          table.setTotalWidth(PageSize.A4.getWidth()- 100);          table.setLockedWidth(true);          // 创建头          PdfPHeaderCell header = new PdfPHeaderCell();          header.addElement(new Paragraph(title, font));          header.setColspan(4);          table.addCell(header);          // 添加内容          table.addCell(new Paragraph("黄河远上白云间",font));          table.addCell(new Paragraph("一片孤城万仞山",font));          table.addCell(new Paragraph("羌笛何须怨杨柳",font));          table.addCell(new Paragraph("春风不度玉门关",font));             document.add(table);          // 关闭文档,才能输出          document.close();          writer.close();     }        public static void main(String[] args) throws Exception {          create();     }  }

3.字体

立即学习前端免费学习笔记(深入)”;

我们项目文书字体比较特殊,比如用到了宋体(99%都这个吧)、华文仿宋(安装office后自带)、仿宋_GB2312等,于是就研究了一下pdf字体,网上有很多方法使用中文字体,其实5.0版以后的iText加入字体还是很方便的。

还是HelloWorld例子:

import java.io.FileOutputStream;  import com.itextpdf.text.Document;  import com.itextpdf.text.Font;  import com.itextpdf.text.FontFactoryImp;  import com.itextpdf.text.Paragraph;  import com.itextpdf.text.pdf.PdfWriter;  import com.itextpdf.tool.xml.XMLWorkerFontProvider;     /**  * 字体  *  * @author zhangwd  * @version 1.0  *  */  public class PdfDemo_2 {         public static void create() throws Exception {          Document document = new Document();          PdfWriter writer = PdfWriter.getInstance(document,new FileOutputStream("c:/demo.2.pdf"));          String title = "凉州词";          String content = "黄河远上白云间,一片孤城万仞山。羌笛何须怨杨柳,春风不度玉门关。";          document.open();          document.add(newParagraph(title, getFont("方正兰亭黑简体")));          document.add(newParagraph(content, getFont("迷你简娃娃篆")));          document.close();          writer.close();      }         private static Font getFont(String fontName) {          // xmlworker主要功能是html转pdf用的,非常好用,也是itext官方的             // 这个是xmlworker提供的获取字体方法,很方便,对中文支持很好          FontFactoryImp fp = newXMLWorkerFontProvider();          // 注册指定的字体目录,默认构造方法中会注册全部目录,我这里注册了src/font目录          fp.registerDirectory(PdfDemo_2.class.getClassLoader().getResource("font").getFile(), true);             // 最好的地方是直接支持获取中文的名字          return fp.getFont(fontName);             // 当然,最好的方法是自己继承XMLWorkerFontProvider,提供一些常用字体,简单方便      }         public static void main(String[]args) throws Exception {          create();      }  }

xmlworker的XMLWorkerFontProvider提供了很方便的获取字体方法:

1.注册一个文件夹,里面有哪些字体都可以,比如我demo中的字体

2.使用getFont(字体名)即可获得,不过字体名从哪来的呢

3.页眉页脚

iText5中并没有之前版本HeaderFooter对象设置页眉和页脚,可以利用PdfPageEvent来完成页眉页脚的设置工作。

PdfPageEvent提供了几个pdf在创建时的事件,页眉页脚就是在每页加载完写入的。

每一页加个页码还是很简单的,但是总页码就麻烦了,iText是流模式的写入内容,只有写到最后,才能知道有多少页,那么显示总页数就麻烦了,不过麻烦不代表不可能。

其实iText仅在调用释放模板方法后才将PdfTemplate写入到OutputStream中,否则对象将一直保存在内存中,直到关闭文档。

所以我们可以在最后关闭文档前,使用PdfTemplate写入总页码。可以理解成先写个占位符,然后统一替换。

Bandy AI
Bandy AI

全球领先的电商设计Agent

下载

还是HelloWorld例子:

package com.thunisoft.demo;  import java.io.FileOutputStream;  import com.itextpdf.text.BaseColor;  import com.itextpdf.text.Document;  import com.itextpdf.text.Element;  import com.itextpdf.text.ExceptionConverter;  import com.itextpdf.text.Font;  import com.itextpdf.text.Image;  import com.itextpdf.text.PageSize;  import com.itextpdf.text.Paragraph;  import com.itextpdf.text.Rectangle;  import com.itextpdf.text.pdf.ColumnText;  import com.itextpdf.text.pdf.PdfContentByte;  import com.itextpdf.text.pdf.PdfPCell;  import com.itextpdf.text.pdf.PdfPTable;  import com.itextpdf.text.pdf.PdfPageEventHelper;  import com.itextpdf.text.pdf.PdfTemplate;  import com.itextpdf.text.pdf.PdfWriter;  import com.itextpdf.tool.xml.XMLWorkerFontProvider;     /**  * 页眉、页脚  *  * @author zhangwd  * @version 1.0  *  */  public class PdfDemo_3 {         public static void create() throws Exception {          Document document = newDocument(PageSize.A4, 50, 50, 50, 50);          PdfWriter writer = PdfWriter.getInstance(document,new FileOutputStream("c:/demo.3.pdf"));             // 增加页眉页脚          writer.setPageEvent(newMyHeaderFooter());             String title = "凉州词";          String content = "黄河远上白云间,一片孤城万仞山。羌笛何须怨杨柳,春风不度玉门关。";          document.open();             Font font = newXMLWorkerFontProvider().getFont("宋体");          for (int i = 0; i <100; i++) {              document.add(newParagraph(title, font));              document.add(new Paragraph(content,font));              document.add(new Paragraph("\n"));          }          document.close();          writer.close();      }         public static void main(String[]args) throws Exception {          create();      }  }     /**  * iText5中并没有之前版本HeaderFooter对象设置页眉和页脚
* 不过,可以利用PdfPageEventHelper来完成页眉页脚的设置工作。
* 就是在页面完成但写入内容之前触发事件,插入页眉、页脚、水印等。
* * @author zhangwd * @version 1.0 * */ class MyHeaderFooter extends PdfPageEventHelper { Font font = new XMLWorkerFontProvider().getFont("宋体", 12, BaseColor.RED); // 总页数 PdfTemplate totalPage; // 打开文档时,创建一个总页数的模版 public void onOpenDocument(PdfWriter writer,Document document) { PdfContentByte cb =writer.getDirectContent(); totalPage = cb.createTemplate(30, 16); } // 一页加载完成触发,写入页眉和页脚 public void onEndPage(PdfWriter writer, Documentdocument) { PdfPTable table = new PdfPTable(3); try { table.setTotalWidth(PageSize.A4.getWidth() - 100); table.setWidths(new int[] { 24, 24, 3}); table.setLockedWidth(true); table.getDefaultCell().setFixedHeight(-10); table.getDefaultCell().setBorder(Rectangle.BOTTOM); table.addCell(new Paragraph("我是文字", font));// 可以直接使用addCell(str),不过不能指定字体,中文无法显示 table.getDefaultCell().setHorizontalAlignment(Element.ALIGN_RIGHT); table.addCell(new Paragraph("第" + writer.getPageNumber() + "页/", font)); // 总页数 PdfPCell cell = new PdfPCell(Image.getInstance(totalPage)); cell.setBorder(Rectangle.BOTTOM); table.addCell(cell); // 将页眉写到document中,位置可以指定,指定到下面就是页脚 table.writeSelectedRows(0, -1, 50,PageSize.A4.getHeight() - 20, writer.getDirectContent()); } catch (Exception de) { throw new ExceptionConverter(de); } } // 全部完成后,将总页数的pdf模版写到指定位置 public void onCloseDocument(PdfWriter writer,Document document) { String text = "总" + (writer.getPageNumber() - 1) + "页"; ColumnText.showTextAligned(totalPage, Element.ALIGN_LEFT, new Paragraph(text,font), 2, 2, 0); } }

4.html转pdf

结果还不错,虽然可以满足我们的要求,但是比较复杂,动态创建一个个的表格和内容过于繁琐,方法太粗暴了,用户的文档内容或格式变化,就要修改程序了。

于是,我们讨论了一个比较好的方法,感谢谢国庆提供的帮助。

先创建html,然后转换成pdf,demo如下:

import java.io.ByteArrayInputStream;  import java.io.FileOutputStream;  import java.io.InputStream;  import java.io.OutputStream;  import com.itextpdf.text.Document;  import com.itextpdf.text.pdf.PdfWriter;  import com.itextpdf.tool.xml.XMLWorkerHelper;     /**  * html转pdf  *  * @author zhangwd  * @version 1.0  *  */  public class PdfDemo_4 {         public static void create() throws Exception {             // html中字体非常郁闷          // 1. html中不指定字体,则默认使用英文字体,中文会不显示。          // 2. html中指定的字体必须是英文名称,如宋体:font-family:SimSun;          // 3. html中不能指定自定义字体,必须指定itext支持的字体,还好itext支持字体比较多,常见操作系统带的都支持          // 4. 暂没有找到如何html中支持自定义字体方法,网上都是修改源码实现默认字体中文,也很重要             StringBuilder html = newStringBuilder();          html.append("");          html.append("");          html.append("");          html.append("");          html.append("");          html.append("");          html.append("");          html.append("");          html.append("");          html.append("");          html.append("
凉州词
黄河远上白云间,一片孤城万仞山。羌笛何须怨杨柳,春风不度玉门关。
"); html.append(""); html.append(""); InputStream is = newByteArrayInputStream(html.toString().getBytes()); OutputStream os = newFileOutputStream("c:/demo.4.pdf"); Document document = new Document(); PdfWriter writer = PdfWriter.getInstance(document,os); document.open(); // 将html转pdf XMLWorkerHelper.getInstance().parseXHtml(writer,document, is); document.close(); } public static void main(String[]args) throws Exception { create(); } }

此处使用了XmlWorker,XmlWorker也是iText官方的,目前和iText版本一起更新,可以讲XHTML转换成pdf,支持大部分样式和标签,是大部分哦,不是全部。

目前我们就用的这个方式,写好html文档,使用时动态替换html中的标记位,然后生成pdf。

使用XHTML转pdf要注意的地方:

1. html中不指定字体,则默认使用英文字体,中文会不显示;网上很多人通过修改源码来实现默认字体中文,也是一种方式,不过感觉比较麻烦。

2. html中指定的字体必须是英文名称;

如宋体:font-family:SimSun;正确

font-family:宋体;则错误,竟然unicode也不行。

3. html中不能指定自定义字体(比如上文中的方正兰亭黑),必须指定iText支持的字体,还好iText支持字体比较多,常见操作系统带的都支持

4. 暂没有找到如何html中支持自定义字体方法。

5. pdf中添加图片也非常简单,例如: 使用iText生成PDF_html/css_WEB-ITnose,就可以了。

6. XHTML不是HTML,所以任何标签都要完整结束,比如
错误,必须
才行。

5.其他

我们项目的文书目前20多种,以后还会大量增加,不过写一个html模版很简单,需要对html和css熟练,调生成的样式部分比较麻烦(比如文字多了会切掉,不切会影响整体样式,表格线有粗有细,xmlworker不支持全部css等),一般A4纸都是厘米单位的,html中最好也使用厘米,处理简单点。

比如我们的部分模版

相关文章

WPS零基础入门到精通全套教程!
WPS零基础入门到精通全套教程!

全网最新最细最实用WPS零基础入门到精通全套教程!带你真正掌握WPS办公! 内含Excel基础操作、函数设计、数据透视表等

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
java入门学习合集
java入门学习合集

本专题整合了java入门学习指南、初学者项目实战、入门到精通等等内容,阅读专题下面的文章了解更多详细学习方法。

2

2026.01.29

java配置环境变量教程合集
java配置环境变量教程合集

本专题整合了java配置环境变量设置、步骤、安装jdk、避免冲突等等相关内容,阅读专题下面的文章了解更多详细操作。

2

2026.01.29

java成品学习网站推荐大全
java成品学习网站推荐大全

本专题整合了java成品网站、在线成品网站源码、源码入口等等相关内容,阅读专题下面的文章了解更多详细推荐内容。

0

2026.01.29

Java字符串处理使用教程合集
Java字符串处理使用教程合集

本专题整合了Java字符串截取、处理、使用、实战等等教程内容,阅读专题下面的文章了解详细操作教程。

0

2026.01.29

Java空对象相关教程合集
Java空对象相关教程合集

本专题整合了Java空对象相关教程,阅读专题下面的文章了解更多详细内容。

3

2026.01.29

clawdbot ai使用教程 保姆级clawdbot部署安装手册
clawdbot ai使用教程 保姆级clawdbot部署安装手册

Clawdbot是一个“有灵魂”的AI助手,可以帮用户清空收件箱、发送电子邮件、管理日历、办理航班值机等等,并且可以接入用户常用的任何聊天APP,所有的操作均可通过WhatsApp、Telegram等平台完成,用户只需通过对话,就能操控设备自动执行各类任务。

25

2026.01.29

clawdbot龙虾机器人官网入口 clawdbot ai官方网站地址
clawdbot龙虾机器人官网入口 clawdbot ai官方网站地址

clawdbot龙虾机器人官网入口:https://clawd.bot/,clawdbot ai是一个“有灵魂”的AI助手,可以帮用户清空收件箱、发送电子邮件、管理日历、办理航班值机等等,并且可以接入用户常用的任何聊天APP,所有的操作均可通过WhatsApp、Telegram等平台完成,用户只需通过对话,就能操控设备自动执行各类任务。

16

2026.01.29

Golang 网络安全与加密实战
Golang 网络安全与加密实战

本专题系统讲解 Golang 在网络安全与加密技术中的应用,包括对称加密与非对称加密(AES、RSA)、哈希与数字签名、JWT身份认证、SSL/TLS 安全通信、常见网络攻击防范(如SQL注入、XSS、CSRF)及其防护措施。通过实战案例,帮助学习者掌握 如何使用 Go 语言保障网络通信的安全性,保护用户数据与隐私。

8

2026.01.29

俄罗斯Yandex引擎入口
俄罗斯Yandex引擎入口

2026年俄罗斯Yandex搜索引擎最新入口汇总,涵盖免登录、多语言支持、无广告视频播放及本地化服务等核心功能。阅读专题下面的文章了解更多详细内容。

622

2026.01.28

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
10分钟--Midjourney创作自己的漫画
10分钟--Midjourney创作自己的漫画

共1课时 | 0.1万人学习

成为PHP架构师-自制PHP框架
成为PHP架构师-自制PHP框架

共28课时 | 2.5万人学习

apipost极速入门
apipost极速入门

共6课时 | 0.5万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号