com.itextpdf.io.IOException Type of font null is not recognized

com.itextpdf.io.IOException: Type of font null is not recognized.

问题描述

使用itext将一个html模板文件转换成pdf文件时,convertToPdf()方法传入ConverterProperties对象,因为Linux服务器上可能会缺少一些字体,通过ConverterProperties对象可以指定使用放在项目下的字体。

程序在IDEA中正常运行,但是服务器上运行构建的jar文件,会得到以下错误:

com.itextpdf.io.IOException: Type of font null is not recognized.
	at com.itextpdf.io.font.FontProgramFactory.createFont(FontProgramFactory.java:240)
	at com.itextpdf.io.font.FontProgramFactory.createFont(FontProgramFactory.java:96)
	at com.employment.common.utils.Html2Pdf.html2pdf(Html2Pdf.java:53)
	……

解决过程

错误发生在方法:FontProgramFactory.createFont中:

尝试很多方式,一直以为是取文件的方式有问题导致的,但发现并不是。

问题原因

.otc或者.ttc文件在打包到jar时被重新编码,导致iText 7-无法识别字体。

将这段代码添加到pom文件的build部分应该可以做到:

            <plugin>
                <artifactId>maven-resources-plugin</artifactId>
                <configuration>
                    <encoding>UTF-8</encoding>
                    <nonFilteredFileExtensions>
                        <nonFilteredFileExtension>ttc</nonFilteredFileExtension>
                    </nonFilteredFileExtensions>
                </configuration>
            </plugin>

部分源码

    @SneakyThrows
    public static void html2pdf(String htmlFile, String pdfFile) {

        log.info("html2pdf is running");

        PdfWriter pdfWriter = new PdfWriter(new File(pdfFile));
        PdfDocument pdfDocument = new PdfDocument(pdfWriter);
        Document doc = new Document(pdfDocument);

        pdfDocument.setDefaultPageSize(PageSize.A4);
        pdfDocument.addEventHandler(PdfDocumentEvent.END_PAGE, new TextFooterEventHandler(doc));

        DefaultFontProvider fontProvider = new DefaultFontProvider();

        //宋体
        FontProgram font1 = FontProgramFactory.createFont(String.valueOf(new Html2Pdf().getClass().getClassLoader().getResource("simsun.ttc,0")));
        if (font1 == null) {
            throw new BizException("ERROR", "没有读取到[simsun.ttc]字体文件!");
        }
        fontProvider.addFont(font1);

        //宋体
        FontProgram font2 = FontProgramFactory.createFont(String.valueOf(new Html2Pdf().getClass().getClassLoader().getResource("宋体-粗体.otf")));

        if (font2 == null) {
            throw new BizException("ERROR", "没有读取到[宋体-粗体.otf]字体文件!");
        }
        fontProvider.addFont(font2);

        ConverterProperties pro = new ConverterProperties();
        pro.setFontProvider(fontProvider);

        log.info("html2pdf开始转换");
        HtmlConverter.convertToPdf(new FileInputStream(htmlFile), pdfDocument, pro);

        log.info("pdf创建成功");
        log.info(pdfFile);
    }
<< 要查看当前 Java 项目的文件编码方式,可以通过以下几种方式进行操作: ### 方法一:使用 IDE(如 IntelliJ IDEA 或 Eclipse) #### 在 IntelliJ IDEA 中: 1. 打开项目后,在菜单栏中选择 `File` -> `Settings` (Windows/Linux) 或者 `IntelliJ IDEA` -> `Preferences` (macOS)。 2. 导航到 `Editor` -> `File Encodings`。 - 这里可以看到两个主要配置项: - **Global Encoding**:全局默认的编码设置。 - **Project Encoding**:当前项目的编码设置。 3. 如果想检查单个文件的编码,可以在编辑器右下角的状态栏找到“Encoding”选项,并点击它即可看到该文件的实际编码。 #### 在 Eclipse 中: 1. 右键点击你想知道其编码方式的具体文件或整个包名,然后选择 `Properties`。 2. 在弹出窗口左侧列表中寻找并选中 "Resource" 部分。 3. 查看右侧展示内容中的 Text file encoding 字段值即为所使用的字符集类型。 ### 方法二:通过程序代码检测 也可以编写简单的Java代码读取文件头信息推测可能采用何种编码标准(但这种方法并不完全可靠),例如UTF8,BOM等有特定标记位可以识别。这里提供一段示例代码用于尝试判断文本文件是否包含BOM从而确定是不是某些特定类型的Unicode格式: ```java import java.io.*; import java.nio.charset.StandardCharsets; import java.util.Arrays; public class FileEncodingChecker { public static void main(String[] args){ try{ checkFile("test.txt"); }catch(Exception e){ System.out.println(e.getMessage()); } } private static void checkFile(String filePath)throws IOException { byte [] bom=new byte[4]; FileInputStream fis=null; try{ fis = new FileInputStream(filePath); if(fis.read(bom)!=bom.length){ throw new RuntimeException("Not enough bytes to identify BOM!"); } // Check for UTF-8 BOM (optional) if(Arrays.equals(bom, new byte[]{(byte)0xEF,(byte)0xBB,(byte)0xBF})){ System.out.println("Detected Charset: UTF-8 with BOM."); return ; } // Check for UTF-16BE & UTF-16LE else if(bom[0]==(byte)0xFE && bom[1]==(byte)0xFF ){ System.out.println("Detected Charset: UTF-16 Big Endian."); return ; } else if(bom[0]==(byte)0xFF && bom[1]==(byte)0xFE ){ System.out.println("Detected Charset: UTF-16 Little Endian."); return ; } // If no recognized BOM was found then assume default platform charset. System.out.println("No explicit BOM detected.Assuming Default OS Encoding:"+StandardCharsets.ISO_8859_1); }finally{ if(fis!=null)fis.close(); } } } ``` 上述代码仅能帮助初步辨识部分带标志符的编码形式比如含有BOM头部字节序列的情况下的编码类别,对于没有明显特征标识的一般ASCII或者其它变体则无法准确辨别需结合业务场景综合考虑实际应用环境而定。 给出了解释之后我们再来看几个关于这个主题相关的疑问点吧!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

朱茂强

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值