如何为iText7/pdfhtml设置默认字体?HTML转PDF表格字体异常排查
解决iText HtmlConverter字体不符合需求的问题
你的问题主要出在两个核心点上:
- 默认的
DefaultFontProvider没有正确注册Verdana的粗体、斜体变体,导致遇到<b>/<i>标签时,找不到对应的Verdana字体,只能回退到系统中的其他替代字体(比如AgencyFB粗体、BookAntiqua斜体)。 - 直接给转换后的元素强制设置
Property.FONT的方式,既无法适配HTML标签自带的字体变体需求,也没针对性地处理第二个评论中span的特殊字体要求。
下面是具体的修复方案:
1. 自定义FontProvider,确保字体变体齐全
首先创建一个自定义字体提供器,注册Verdana的所有必要变体(常规、粗体、斜体、粗斜体)以及AgencyFB,并将全局默认字体设置为Verdana,这样所有未指定字体的文本都会优先使用Verdana。
public class CustomFontProvider : DefaultFontProvider { public CustomFontProvider() : base(false, false, true) { // 注册Verdana的各个字体变体(根据实际情况调整:系统字体用名称,嵌入字体用文件路径) AddFont("Verdana", PdfEncodings.CP1252); AddFont("Verdana Bold", PdfEncodings.CP1252); AddFont("Verdana Italic", PdfEncodings.CP1252); AddFont("Verdana Bold Italic", PdfEncodings.CP1252); // 注册AgencyFB字体 AddFont("AgencyFB", PdfEncodings.CP1252); // 设置全局默认字体为Verdana SetDefaultFont("Verdana"); } }
提示:如果使用嵌入字体(而非系统已安装字体),需要将字体文件(如
Verdana.ttf、VerdanaBold.ttf)添加到项目中,并在AddFont时指定正确路径,例如AddFont(@"Fonts/Verdana.ttf", PdfEncodings.CP1252)。
2. 调整HtmlConverter的转换逻辑
更新InsertHtmlCell方法,使用自定义的CustomFontProvider,同时移除直接强制设置元素字体的代码,让字体提供器自动处理默认字体逻辑:
private void InsertHtmlCell(Table table, float defaultFontSize, string comment) { var cell = new Cell(1, 1); ConverterProperties prop = new ConverterProperties(); // 绑定自定义字体提供器 prop.SetFontProvider(new CustomFontProvider()); // 设置全局默认字体大小 prop.SetFontSize(defaultFontSize); var elements = HtmlConverter.ConvertToElements(comment, prop).Cast<IBlockElement>(); foreach (var element in elements) { // 不再强制覆盖元素字体,交给FontProvider处理默认规则 cell.Add(element); } table.AddCell(cell); }
3. 给第二个评论的span指定特殊字体
根据需求,仅第二个示例的span使用AgencyFB,所以修改comment2的HTML,给每个span加上font-family: 'AgencyFB'的样式:
string comment2 = "<div><span style=\"font-size: 18px; font-family: 'AgencyFB'\">large</span><div><div><span style=\"font-size: 11px; font-family: 'AgencyFB'\">medium</span><div><div><span style=\"font-size: 8px; font-family: 'AgencyFB'\">small</span></div>";
4. 调整主方法的调用逻辑
修改CreateDoc中调用InsertHtmlCell的代码,不再传递默认字体参数(字体逻辑已由CustomFontProvider接管):
public byte[] CreateDoc() { using (MemoryStream stream = new MemoryStream()) { using (PdfWriter writer = new PdfWriter(stream)) { PdfDocument pdfDoc = new PdfDocument(writer); Document doc = new Document(pdfDoc, PageSize.A4); float fontSize = 11f; Table table = new Table(1); table.AddCell(new Cell().Add(new Paragraph("no Html").SetFont(PdfFontFactory.CreateRegisteredFont("Verdana", PdfEncodings.CP1252, true)).SetFontSize(fontSize))); string comment1 = "<div>a <b>bold</b> and an <i>italic</i> text.</div>"; string comment2 = "<div><span style=\"font-size: 18px; font-family: 'AgencyFB'\">large</span><div><div><span style=\"font-size: 11px; font-family: 'AgencyFB'\">medium</span><div><div><span style=\"font-size: 8px; font-family: 'AgencyFB'\">small</span></div>"; InsertHtmlCell(table, fontSize, comment1); InsertHtmlCell(table, fontSize, comment2); doc.Add(table); doc.Close(); pdfDoc.Close(); } return stream.ToArray(); } }
修复原理说明
- 自定义FontProvider确保了Verdana的所有变体都能被找到,
<b>会自动使用Verdana Bold,<i>会使用Verdana Italic,不会再回退到其他字体。 - 全局默认字体设为Verdana,所以第一个评论的所有文本(普通、粗体、斜体)都会使用Verdana。
- 第二个评论的span通过
font-family样式指定使用AgencyFB,FontProvider会正确加载并应用该字体,满足你的特殊需求。
内容的提问来源于stack exchange,提问作者Penguin
相关产品推荐
相关产品推荐

