名称 | 语言 | 许可 | 系统 | 架构 | 主要依赖 | 自主开发 | 中文乱码 | 字体引用 | CSS2 | CSS3 | SVG | CANVAS | 图片越界 | 表单 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
princexml | java8、11 | 需要 | win10 centos7 | x86_64 | prince | 不支持 | 无 | 无 | 支持 | 支持 | 支持 | 支持 | 有 | |
itext5、8 | java8、11 | AGPLV3 | win10 centos7 | x86_64 | html2pdf | 支持 | 无 | 无 | 支持 | 支持 | 支持 | - | 有 | |
openpdf | java8、11 | LGPL2.1 MPL2.0 | win10 centos7 | x86_64 | flying-saucer-pdf-openpdf 版本较新 | 支持 | 无 | ? | 支持 | 支持 | ? | ? | 有 | |
pdfbox | java8、11 | Apache2.0 LGPL2.1 | win10 centos7 | x86_64 | openhtmltopdf-pdfbox2、3 版本升级? | 支持 | 无 | ? | 支持 | 支持 | ? | ? | 有 | |
selenium | java11+ | Apache 2.0 | win10 | x86_64 | selenium-java 4.16 firefox116 | 不支持 | 无 | 支持 | 支持 | 支持 | 支持 | 支持 | 有 | |
selenium | java11+ | Apache 2.0 | centos7 | x86_64 | selenium-java 4.16 | 不支持 | 无 | 支持 | 支持 | 支持 | 支持 | 支持 | 有 | |
selenium | python3.7.9 | ? | win10 | x86_64 | selenium4.11 firefox116 | 不支持 | 无 | 支持 | 支持 | 支持 | 支持 | 支持 | 有 | |
selenium | python3.8.18 | ? | centos7 | x86_64 | selenium4.16 firefox102 | 不支持 | 无 | 支持 | 支持 | 支持 | 支持 | 支持 | 有 | |
selenium | python3.6+ | ? | centos7 | x86_64 | selenium3.141 firefox102 | - | - | - | - | - | - | - | - | |
weasyprint | python3.7.9 | BSD | win10 | x86_64 | gtk3+ | 支持 | 无 | 无 | 支持 | 支持 | 支持 | 无 | 有 | |
weasyprint | python3.9.18 | BSD | stream9 | x86_64 | cairo,Pango,gtk2.6+ | 支持 | 无 | 无 | 支持 | 支持 | 支持 | 无 | 有 | |
xhtml2pdf | python3.8+ | stream9 | x86_64 | openssl1.1.1+ | ? | 有 | - | - | - | - | - |
名称 | prince | itext | selenium | openpdf | pdfbox | weasyprint |
---|---|---|---|---|---|---|
效果 | 1 | 1 | 1 | 0.5 | 0.5 | 0.5 |
授权 | 0 | 0 | 1 | 0 | 1 | 1 |
系统 | 0.5 | 1 | 1 | 1 | 1 | 0.5 |
架构 | 0.5 | 1 | 1 | 1 | 1 | 1 |
自主开发 | 0 | 0.5 | 0 | 1 | 1 | 1 |
总分 | 2 | 3.5 | 4 | 3.5 | 4.5 | 4 |
It’s quick and simple to convert HTML to PDF with Prince. HTML is seamlessly transformed into documents you can print
下载地址
Prince - Download Prince 15.2 (princexml.com)
java
C#
PHP
Node
Ruby
系统名称 | x86_64 | arm64 | 说明 |
---|---|---|---|
Windows | 有 | - | |
Red Hat Enterprise Linux 7-9 | 有 | - | |
Ubuntu 18-22 | 有 | 有 | |
Debian GNU Linux 9-10 | 有 | - | |
Debian GNU Linux 11-12 | 有 | 有 | |
OpenSUSE | 有 | - | |
MacOS | ? | ? | |
Alpine Linux | 有 | - | |
Generic Linux | 有 | 有 | |
Free BSD | 有 | - |
<dependency>
<groupId>com.princexml</groupId>
<artifactId>prince-java-wrapper</artifactId>
<version>1.3.0</version>
</dependency>
// 获取 java 版本
String version = System.getProperty("java.specification.version");
// 获取系统类型
String platform = System.getProperty("os.name", "");
platform = platform.toLowerCase().contains("window") ? "win" : "linux";
// 当前程序目录
String current = System.getProperty("user.dir");
System.out.println(String.format("current=%s", current));
// html 文件路径
File index = Paths.get(current, "..", "index.html").toFile();
if (!index.exists()) {
System.out.println(String.format("file not exist,file=%s", index.getAbsolutePath()));
return;
}
String command = Paths.get(current, "..", "prince-15.2-win64", "bin", "prince.exe").toString();
if (OSInfo.getOSType() == OSInfo.OSType.LINUX) {
command = "prince";
}
Prince prince = new Prince(command);
// prince.setLog("/path/to/log.txt");
// prince.addStyleSheet("/path/to/stylesheet.css");
// prince.addScript("/path/to/script.js");
prince.setJavaScript(true);
try {
// 转换 html 文件
File file = Paths.get(current, String.format("java%s_%s.pdf", version, platform)).toFile();
prince.convert(index.getAbsolutePath(), file.getAbsolutePath());
} catch (IOException e) {
e.printStackTrace();
}
![](D:\work\linux-html2pdf-demo\images\屏幕截图 2023-12-16 171211.png)
<dependency>
<!-- 会自动引用 itext 其他库,kernel,commons,io,forms,layout,svg,styled-xml-parser -->
<groupId>com.itextpdf</groupId>
<artifactId>html2pdf</artifactId>
<version>5.0.2</version>
</dependency>
![](D:\work\linux-html2pdf-demo\images\屏幕截图 2023-12-16 172507.png)
// 获取 java 版本
String version = System.getProperty("java.specification.version");
// 获取系统类型
String platform = System.getProperty("os.name", "");
platform = platform.toLowerCase().contains("window") ? "win" : "linux";
// 当前程序目录
String current = System.getProperty("user.dir");
System.out.println(String.format("current=%s", current));
// html 文件路径
File index = Paths.get(current, "..", "index.html").toFile();
if (!index.exists()) {
System.out.println(String.format("file not exist,file=%s", index.getAbsolutePath()));
return;
}
try {
// 保存 pdf 文件路径
File file = Paths.get(current, String.format("java%s_%s.pdf", version, platform)).toFile();
// 转换设置
ConverterProperties options = new ConverterProperties();
// 设置根目录类型
String baseUri = Paths.get(current, "..").toUri().toString();
options.setBaseUri(baseUri);
// 设置字体
FontProvider fontProvider = new FontProvider();
fontProvider.addStandardPdfFonts();
fontProvider.addSystemFonts();
options.setFontProvider(fontProvider);
// 转换 html 文件
HtmlConverter.convertToPdf(index, file, options);
} catch (IOException e) {
throw new RuntimeException(e);
}
<dependency>
<!-- 将 html 转换为 xml 工具库 -->
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.17.1</version>
</dependency>
<dependency>
<!-- 第三方 openpdf 包装库,提供 html 转 pdf 功能 -->
<groupId>org.xhtmlrenderer</groupId>
<artifactId>flying-saucer-pdf-openpdf</artifactId>
<version>9.3.1</version>
</dependency>
// 获取 java 版本
String version = System.getProperty("java.specification.version");
// 获取系统类型
String platform = System.getProperty("os.name", "");
platform = platform.toLowerCase().contains("window") ? "win" : "linux";
// 当前程序目录
String current = System.getProperty("user.dir");
System.out.println(String.format("current=%s", current));
// html 文件路径
File index = Paths.get(current, "..", "index.html").toFile();
if (!index.exists()) {
System.out.println(String.format("file not exist,file=%s", index.getAbsolutePath()));
return;
}
try {
Document document = Jsoup.parse(index, "UTF-8");
// 补全标记
document.outputSettings().syntax(Document.OutputSettings.Syntax.xml);
ITextRenderer render = new ITextRenderer();
ITextFontResolver fontResolver = render.getFontResolver();
File[] fonts = Paths.get(current, "..", "fonts").toFile().listFiles();
for (File item : fonts) {
// 应该这样添加字体
fontResolver.addFont(item.getAbsolutePath(), BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
}
SharedContext sharedContext = render.getSharedContext();
sharedContext.setPrint(true);
sharedContext.setInteractive(false);
sharedContext.getTextRenderer().setSmoothingThreshold(0);
// 自定义图片解析
// sharedContext.setReplacedElementFactory(new ReplacedElementFactoryImpl());
// 指定根目录,这里需要 URL 格式
// file:/D:/work/linux-html2pdf-demo/openpdf-demo/../
String baseUrl = Paths.get(current, "..").toUri().toURL().toString();
render.setDocumentFromString(document.html(), baseUrl);
render.layout();
File file = Paths.get(current, String.format("java%s_%s.pdf", version, platform)).toFile();
FileOutputStream stream = new FileOutputStream(file);
render.createPDF(stream);
stream.close();
System.out.println(String.format("file=%s", file.getAbsolutePath()));
} catch (IOException e) {
throw new RuntimeException(e);
}
<!-- 将 html 转换为 xml 工具库 -->
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.17.1</version>
</dependency>
<!-- 第三方 pdfbox 包装库,提供 html 转 pdf 功能 -->
<dependency>
<groupId>com.openhtmltopdf</groupId>
<artifactId>openhtmltopdf-pdfbox</artifactId>
<version>1.0.10</version>
</dependency>
// 获取 java 版本
String version = System.getProperty("java.specification.version");
// 获取系统类型
String platform = System.getProperty("os.name", "");
platform = platform.toLowerCase().contains("window") ? "win" : "linux";
// 当前程序目录
String current = System.getProperty("user.dir");
System.out.println(String.format("current=%s", current));
// html 文件路径
File index = Paths.get(current, "..", "index.html").toFile();
if (!index.exists()) {
System.out.println(String.format("file not exist,file=%s", index.getAbsolutePath()));
return;
}
try {
Document doc = Jsoup.parse(index, "UTF-8");
// 补全标记
doc.outputSettings().syntax(Document.OutputSettings.Syntax.xml);
File file = Paths.get(current, String.format("java%s_%s.pdf", version, platform)).toFile();
FileOutputStream stream = new FileOutputStream(file);
PdfRendererBuilder builder = new PdfRendererBuilder();
// NOTE 字体问题,文档中出现过的字段,需要手动加载字体
builder.useFont(Paths.get(current, "..", "fonts", "simsun.ttc").toFile(), "SimSun");
builder.useFont(Paths.get(current, "..", "fonts", "msyh.ttc").toFile(), "font-test");
builder.useFont(Paths.get(current, "..", "fonts", "msyh.ttc").toFile(), "Microsoft YaHei UI");
// NOTE 设置根目录
String baseUrl = Paths.get(current, "..").toUri().toString();
builder.withHtmlContent(doc.html(), baseUrl);
builder.toStream(stream);
builder.run();
} catch (IOException e) {
throw new RuntimeException(e);
}
# 查看 pdf 内部结构
java -jar pdfbox-app debug path-to-pdf/test.pdf
java -jar debugger-app path-to-pdf/test.pdf
Selenium 通过使用 WebDriver 支持市场上所有主流浏览器的自动化。 Webdriver 是一个 API 和协议,它定义了一个语言中立的接口,用于控制 web 浏览器的行为。 每个浏览器都有一个特定的 WebDriver 实现,称为驱动程序。 驱动程序是负责委派给浏览器的组件,并处理与 Selenium 和浏览器之间的通信。
这种分离是有意识地努力让浏览器供应商为其浏览器的实现负责的一部分。 Selenium 在可能的情况下使用这些第三方驱动程序, 但是在这些驱动程序不存在的情况下,它也提供了由项目自己维护的驱动程序。
Selenium 框架通过一个面向用户的界面将所有这些部分连接在一起, 该界面允许透明地使用不同的浏览器后端, 从而实现跨浏览器和跨平台自动化。
# selenium 驱动
https://selenium-python.readthedocs.io/installation.html#drivers
https://selenium-python.readthedocs.io/api.html
-i http://172.16.51.188:8081/repository/pypi/simple --trusted-host 172.16.51.188
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>4.16.1</version>
</dependency>
// 获取 java 版本
String version = System.getProperty("java.specification.version");
// 获取系统类型
String platform = System.getProperty("os.name", "");
platform = platform.toLowerCase().contains("window") ? "win" : "linux";
// 当前程序目录
String current = System.getProperty("user.dir");
System.out.println("current:" + current);
// firefox 运行参数配置
FirefoxOptions options = new FirefoxOptions();
// 无头模式
options.addArguments("--headless");
// 最大化
options.addArguments("--start-maximized");
FirefoxDriver browser = new FirefoxDriver(options);
Path url = Paths.get(current, "..", "index.html");
System.out.println("url:" + url.toString());
// NOTE 要使用 file 协议
browser.get(String.format("file://%s", url.toString()));
// 打印设置
PrintOptions print = new PrintOptions();
Pdf pdf = browser.print(print);
// pdf base64 内容
String content = pdf.getContent();
// 解码内容
Base64.Decoder decoder = Base64.getDecoder();
byte[] buffer = decoder.decode(content);
try {
// 将 byte 写入文件
Path file = Paths.get(String.format("java%s_%s.pdf", version, platform));
Files.write(file, buffer);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
browser.quit();
}
Selenium 通过使用 WebDriver 支持市场上所有主流浏览器的自动化。 Webdriver 是一个 API 和协议,它定义了一个语言中立的接口,用于控制 web 浏览器的行为。 每个浏览器都有一个特定的 WebDriver 实现,称为驱动程序。 驱动程序是负责委派给浏览器的组件,并处理与 Selenium 和浏览器之间的通信。
pip install selenium -i http://172.16.51.188:8081/repository/pypi/simple --trusted-host 172.16.51.188
import os
import sys
import base64
from selenium import webdriver
platform = 'win' if sys.platform == 'win32' else 'linux'
current = os.path.abspath(os.path.dirname(__file__))
options = webdriver.FirefoxOptions()
options.add_argument('--headless')
options.add_argument("--start-maximized")
# options.add_argument('--disable-gpu')
browser = webdriver.Firefox(options=options)
browser.get(
'file://{}'.format(os.path.join(current, '..', 'index.html'))
)
data = browser.print_page()
buffer = base64.b64decode(data)
version = sys.version_info
file = os.path.join(
current, 'python{}{}{}_{}.pdf'.format(
version.major,
version.minor,
version.micro,
platform
)
)
with open(file, 'wb') as fd:
fd.write(buffer)
browser.quit()
WeasyPrint 能在 Linux, macOS and Windows 多平台支持,因为WeasyPrint需要依赖cairo, Pango 和 GDK-PixBuf ,所以这些软件需要独立安装
Python ≥ 3.7.0
手动编译 3.8.18
Pango ≥ 1.44.0
centos7 默认是 1.43 手动编译 1.45.5 版本 安装编译工具 meson
# centos7 默认 0.55.1;
yum install meson
编译时依赖检查失败 glib2.6+ 猜测需要 高版本的系统
pydyf ≥ 0.6.0
CFFI ≥ 0.6
html5lib ≥ 1.1
tinycss2 ≥ 1.0.0
cssselect2 ≥ 0.1
Pyphen ≥ 0.9.1
Pillow ≥ 9.1.0
fontTools ≥ 4.0.0
# linux 环境依赖
yum install pango gcc python3-devel gcc-c++ zlib-devel libjpeg-devel openjpeg2-devel libffi-devel
# windows 环境依赖
需要安装 gtk3 https://github.com/tschoonj/GTK-for-Windows-Runtime-Environment-Installer/releases/tag/2022-01-04
# 使用命令,有乱码问题
weasyprint index.html wessy.pdf
代码测试,见测试代码
基于 ReportLab、html5lib、PyPDF2 等 Python 模块构建的 HTML 到 PDF 转换模块。能够很好的支持 HTML5 、CSS2.1 和部分 CSS3 语法。
因为是基于 Report Lab 模块进行的开发,其对中文的支持在某些环境下会有问题。而且由于开发人员的变更,模块的功能出现了一些断层
# openssl 编译
wget --no-check-certificate https://www.openssl.org/source/openssl-1.1.1w.tar.gz
./config --prefix=/usr/local/openssl-1.1.1w
tar -xvf openssl-1.1.1w.tar.gz
cd openssl-1.1.1w
make -j4
make -j4 install
# 重新编译 python 以支持 openssl 1.1.1w
./configure --prefix=/usr/local/python38 --with-openssl=/usr/local/openssl-1.1.1w/
make -j4
make -j4 install
# 验证 python 关联 openssl 版本
import ssl
print(ssl.OPENSSL_VERSION)
# 安装
pip install xhtml2pdf -i http://172.16.51.188:8081/repository/pypi/simple --trusted-host 172.16.51.188
# 测试,有乱码问题,没有代码实现过
xhtml2pdf index.html xhtml.pdf
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。