iTextSharp HTML到PDF转换 - 无法更改字体

Fra*_*nko 1 html pdf asp.net-mvc fonts itextsharp

我正在使用ASP.NET MVC5应用程序中的HTML从iTextSharp(5.5.7.0)创建一些PDF文档,但我无法更改字体.我已经尝试了几乎所有我能在SO或其他资源上找到的东西.

PDF生成代码如下:

    public Byte[] GetRecordsPdf(RecordsViewModel model)
    {
        var viewPath = "~/Template/RecordTemplate.cshtml";
        var renderedReport = RenderViewToString(viewPath, model);

        FontFactory.RegisterDirectory(Environment.GetFolderPath(Environment.SpecialFolder.Fonts));

        using (var ms = new MemoryStream())
        {
            using (var doc = new Document())
            {
                doc.SetPageSize(PageSize.A4.Rotate());

                using (var writer = PdfWriter.GetInstance(doc, ms))
                {
                    doc.Open();

                    using (var html = new MemoryStream(Encoding.Default.GetBytes(renderedReport)))
                    {
                        XMLWorkerHelper.GetInstance().ParseXHtml(writer, doc, html, Encoding.Default);
                    }

                    doc.Close();
                }
            }

            var bytes = ms.ToArray();
            return bytes;
        }
    }
Run Code Online (Sandbox Code Playgroud)

实际的HTML包含在renderedReport字符串变量中(我有强类型的.cshtml文件,我使用MVC Razor引擎渲染,然后在字符串中返回HTML).

我试图注册一些特定的字体,但这没有帮助.我也尝试在我的机器上注册所有字体(如上例所示),但这也没有帮助.加载了字体我在调试模式下检查过.

CSS嵌入在HTML文件中(在标题,样式标记中),如下所示:

    body {
        font-size: 7px;
        font-family: Comic Sans MS;
    }
Run Code Online (Sandbox Code Playgroud)

(为了测试,我决定使用Comic Sans,因为我可以轻松识别它,我实际上对Arial Unicode MS更感兴趣).

而且我实际上能够使用CSS中的font-family属性更改字体,但仅限于默认情况下由iTextSharp预装的字体 - Times New Roman,Arial,Courier和其他一些(我认为是Helvetica).当我将其更改为 - 漫画Sans,或其他未预加载的iTextSharp渲染时使用默认字体(Arial我会说).

我需要更改字体的原因是因为我在我的渲染HTML(ČĆŠĐŽčćšđž)中有一些克罗地亚字符,这些字符在PDF中缺失,目前我认为主要原因是 - 字体.

我错过了什么?

Chr*_*aas 7

有几件事要做这件事.

首先,默认情况下XMLWorkerHelper不使用FontFactory,你需要使用其中一个重载来ParseXHtml()获取IFontProvider.这两个重载都要求您Stream为CSS文件指定一个,但null如果您的CSS存在于HTML文件中,则可以通过.幸运的是FontFactory有一个静态属性,可以实现这个,你可以使用被调用FontFactory.FontImp

//                                                                                 **This guy**
XMLWorkerHelper.GetInstance().ParseXHtml(writer, doc, msHTML, null, Encoding.UTF8, FontFactory.FontImp);
Run Code Online (Sandbox Code Playgroud)

其次,我知道你说你试图在绝望中注册你的整个字体目录,但这可能是一个相当昂贵的电话.如果可以,请始终尝试只注册所需的字体.虽然是可选的,但我还强烈建议您明确定义字体的别名,因为字体可以有多个名称,但它们并不总是我们想的.

FontFactory.Register(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Fonts), "comic.ttf"), "Comic Sans MS");
Run Code Online (Sandbox Code Playgroud)

第三,这可能不会对您产生影响,但HTML中没有的任何标签,即使它们在逻辑上是暗示的,也不会从CSS中应用样式.这听起来很奇怪,所以换句话说,如果你的HTML只是<p>Hello</p>你的CSS body{font-size: 7px;},那么字体大小将不会被应用,因为你的HTML缺少<body>标签.

第四,这是可选的,但通常更容易指定你的HTML和CSS彼此分开,我将在下面的例子中做.

你的代码是95%那么只需要几个调整它应该工作.我只是解析原始HTML和CSS而不是视图,但您可以根据需要进行修改.请记住(我想你知道这一点)iTextSharp 无法处理ASP.Net,只能处理HTML,所以你需要确保你的ASP.Net到HTML转换过程是理智的.

//Sample HTML and CSS
var html = @"<body><p>Sva ljudska bi?a ra?aju se slobodna i jednaka u dostojanstvu i pravima. Ona su obdarena razumom i sviješ?u i trebaju jedna prema drugima postupati u duhu bratstva.</p></body>";
var css = "body{font-size: 7px; font-family: Comic Sans MS;}";

//Register a single font
FontFactory.Register(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Fonts), "comic.ttf"), "Comic Sans MS");

//Placeholder variable for later
Byte[] bytes;

using (var ms = new MemoryStream()) {
    using (var doc = new Document()) {
        doc.SetPageSize(PageSize.A4.Rotate());

        using (var writer = PdfWriter.GetInstance(doc, ms)) {
            doc.Open();

            //Get a stream of our HTML
            using (var msHTML = new MemoryStream(Encoding.UTF8.GetBytes(html))) {

                //Get a stream of our CSS
                using (var msCSS = new MemoryStream(Encoding.UTF8.GetBytes(css))) {

                    XMLWorkerHelper.GetInstance().ParseXHtml(writer, doc, msHTML, msCSS, Encoding.UTF8, FontFactory.FontImp);
                }
            }

            doc.Close();
        }
    }

    bytes = ms.ToArray();
}
Run Code Online (Sandbox Code Playgroud)