前言

Windows中JAVA使用wkhtmltox工具转换HTML为PDF过程中出现了乱码,本文详细解释我遇见的乱码问题以及解决方法

⚠️:此片文章基于Windows操作系统

相关文章(本文与这两篇有密切关系):


一、乱码错误

1、错误目标网址

https://12366.chinatax.gov.cn/bsznBLH/print?bh=8d74c639bf954fd988c872ae548612df

2、错误说明

  • 👇转换的PDF文件里的表格中部分字体乱码,乱码字体属于黑体

3、错误截图

pic_4


二、乱码解决方法

原因分析

macOS操作系统中的wkhtmltox工具转换的PDF文件并没有出现该字体乱码问题,但Windows操作系统则是出现了以上问题(转图片无影响);与java程序并无具体关系,因为在cmd黑窗口中运行该工具时转换的PDF文件就已经出现了该问题

  • 第一次尝试:我尝试在别的最新版本的Windows系统中执行该工具转换,发现跟系统版本没有任何关系。

  • 第二次尝试:我在网络上寻找解决办法中,大多数都是说字体缺失,但是我的电脑中不存在缺失黑体字体的问题,但就是这个表格中的黑体字出现了乱码错误,其它部分一切正常。

  • 第三次尝试:我在想能不能通过java程序在每次转换之前将原网址的黑体字全部扫描且更换为别的字体,按照这个想法才最终解决了乱码问题(其实不算解决、但又解决了:如解 具体看下面的方法跟解释吧)

1、自定义字体文件

解决这次乱码问题的方法就是引入自定义的CSS文件;通过改变原来网页代码中的字体样式,从而达到解决乱码问题的目的

css文件代码如下
1
2
3
4
5
6
7
8
9
10
<style>
@font-face {
font-family:myFont;
src:url("C:\\Windows\\Fonts\\simhei.ttf");
}

.MsoNormal * {
font-family:myFont !important;
}
</style>

//创建一个css文件,将上面代码复制进去即可

  • @font-face:引入系统字体文件,可以引入多种字体

  • C:\Windows\Fonts\simhei.ttf:是windows系统黑体文字所在的位置

  • myFont:自定义的字体名称,切勿使用“黑体”,“宋体”等字样作为自定义名称,否则无效

  • .MsoNormal *:将MsoNormal类名下的所以字体改为黑体(需要更改别的类下的字体,也是这样)

2、在JAVA中引入自定义字体文件

引入自定义字体文件的路径

1
2
//由于wkhtmltox对于某些字体转换失效,需要引入的自定义css文件;文件位置可自定义,最好是放在项目中(对于是路径定义这里不细说,都是直接全路径引用)
private static final String FONT_URL = "C:/wkhtmltox/wkhtmltopdf/styleFont.css";

这次的修改代码以JAVA使用wkhtmltox工具生成PDF、图片文件一文中的代码为基础,转换为图片的方法无需修改

具体修改代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
/**
* html转PDF
*
* @param htmlUrl 网页地址
* @return 返回pdf保存地址
*/
public static void htmlToPdf(String htmlUrl) {
//保存路径
String pdfPath = FILE_PDF_PATH + FILE_NAME + ".pdf";
//创建文件
File file = new File(pdfPath);
File parent = file.getParentFile();
//如果pdf保存路径不存在,则创建路径
if (!parent.exists()) {
parent.mkdirs();
}
logger.info("----------------------- 开始html转pdf操作");
StringBuilder cmd = new StringBuilder();
cmd.append(WKHTMLTOX_PDF_PATH);
cmd.append(" ");
cmd.append("-B 0 -L 0 -R 0 -T 0 ");
//开启本地文件访问
cmd.append("--enable-local-file-access ");
//设置每页参数(注意,数值后面需要加一个空格,如:"10mm ")
//cmd.append(" --encoding <UTF-8> ");//设置默认的字符编码
//cmd.append(" --minimum-font-size 12 ");//设置最小字体大小 (default 5)
cmd.append(" --margin-top 10mm ");//设置页面上边距 (default 10mm)cm
cmd.append(" --margin-bottom 10mm ");//设置页面下边距 (default 10mm)cm
cmd.append(" --margin-left 8mm ");//设置页面左边距 (default 10mm)cm
cmd.append(" --margin-right 8mm ");//设置页面右边距 (default 10mm)cm
cmd.append(" --page-offset 1 ");//设置起始页码 (default 1)
cmd.append(" --page-size A4 ");//设置纸张大小: A4, Letter, etc.
cmd.append(" --disable-javascript ");//禁用网页中的JavaScript功能
cmd.append(" --debug-javascript ");//显示打印调试信息
//当前操作系统为Windows时,才引入自定义样式
if (OS.startsWith("Windows")) {
cmd.append(" --user-style-sheet ").append(FONT_URL).append(" ");//引入自定义样式
}
cmd.append(HTML_URL).append(" ");
cmd.append(pdfPath);
try {
Process proc = Runtime.getRuntime().exec(cmd.toString());
HtmlToXInterceptor error = new HtmlToXInterceptor(proc.getErrorStream());
HtmlToXInterceptor output = new HtmlToXInterceptor(proc.getInputStream());
error.start();
output.start();
proc.waitFor();
logger.info("----------------------- html转pdf成功:html路径:{} pdf保存路径:{}", htmlUrl, pdfPath);
} catch (Exception e) {
e.printStackTrace();
logger.error("----------------------- html转pdf失败:html路径:{} pdf保存路径:{}", htmlUrl, pdfPath);
} finally {
logger.info("----------------------- 结束html转pdf操作");
}
}

3、成功截图

经过引入css文件,转换后的文件便没有乱码问题了

pic_5


三、问题总结

虽然这样是解决了乱码的问题,但是并不是一个完全解决的办法(但程序跑起来没问题就行)

为什么说是没有完全解决?

我一开始在谷歌浏览器将网页保存到本地,然后将上面的css代码写入到保存在本地的html文件中,我发现确实能扫描到这个类名下的所有字符且更改为我设定的字体。

但是,这是在本地修改的,然而wkhtmltox工具是线上实时转换html为PDF的;因此无论我引入什么楷体、黑体、宋体或是其他字体,最终转换的PDF文件中的字体都是宋体。

因此,虽然在JAVA中引入字体文件能解决乱码,但是最终效果却不显示自定义的字体,而是显示宋体。

我猜测,大概率是因为在实时转换中,我引入的黑体字(内部样式)与原网页中定义的字体(行内样式)发生了冲突,然后系统自动选择了一个默认的字体(宋体),所以才达到解决乱码但字体没有按自定义显示的效果

前端知识的欠缺还是导致我无法完全解释这一问题,所以还是需要再研究、深入学习;但是出现此乱码问题在本片解决方法中也确实能实现不乱码的结果

最后
  • 这是借助JAVA程序在转换过程中引入css文件才能达到这个效果
  • wkhtmltox工具本身并没有发生任何改变,在Windows的cmd黑窗口中直接将这类型的乱码网页转换为PDF还是会乱码
  • 在macOS操作系统中则不会发生乱码


更多关于JDK的知识持续更新中!!!



借鉴链接


java 代码 用 wkHtmlToPdf 工具生成 pdf 文档 并 设置自定义 字体


声明

借鉴部分均注明了原文出处,可在文章的`借鉴链接`处获取原文出处
文中若内容有涉及原版权,请邮件联系elvin-chen@qq.com,涉及的相关文章或内容将会及时更改或取消发布