用于嵌入式字体的PDFsharp / MigraDoc字体解析器:System.ArgumentException: F

本文关键字:字体 System ArgumentException MigraDoc 嵌入式 PDFsharp 用于 | 更新日期: 2023-09-27 18:13:56

我使用MigraDoc在我的ASP中生成pdf。NET5 MVC6 Web应用程序,部署到Azure云。我使用的是1.50 beta-2版本,但我也尝试过使用v1.50 beta-1和v1.32。

当应用程序在本地运行时,我已经成功地生成了pdf。然而,当应用程序在云服务器上运行时,由于无法访问任何字体,我在生成pdf时遇到了很大的麻烦。遵循PDFsharp文档,我尝试通过在我的代码中嵌入字体来创建一个"私有字体"。

我成功地在云端直接使用PDFsharp生成pdf文件

    public static MyResolver FontResolver = new MyResolver();
    public void RenderPdf(CreateDocumentViewModel viewModel)
    {
        GlobalFontSettings.FontResolver = FontResolver;
        //...
        XFont font = new XFont("times-roman", 12, XFontStyle.Regular);
        //This font is then used in DrawString.
    }

然而,我现在想利用MigraDoc的优势,这样我就不必自己做所有的排版了。

我遵循了Thomas Hövel博客上的优秀指南(这是beta-2的新指南,尽管我之前也遵循了他早期的beta-1帖子)。他的项目对我来说非常适合,就目前而言。

我实现了在我的Web App项目中使用的示例。它的完全与托马斯的代码相同,除了main是我的控制器中的一个方法,它在按钮点击上运行:

字体解析器类:

public class DemoFontResolver : IFontResolver
{
    public FontResolverInfo ResolveTypeface(string familyName, bool isBold, bool isItalic)
    {
        // Ignore case of font names.
        var name = familyName.ToLower();
        // Deal with the fonts we know.
        switch (name)
        {
            case "ubuntu":
                if (isBold)
                {
                    if (isItalic)
                        return new FontResolverInfo("Ubuntu#bi");
                    return new FontResolverInfo("Ubuntu#b");
                }
                if (isItalic)
                    return new FontResolverInfo("Ubuntu#i");
                return new FontResolverInfo("Ubuntu#");
            case "janitor":
                return new FontResolverInfo("Janitor#");
        }
        // We pass all other font requests to the default handler.
        // When running on a web server without sufficient permission, you can return a default font at this stage.
        return PlatformFontResolver.ResolveTypeface(familyName, isBold, isItalic);
    }
    /// <summary>
    /// Return the font data for the fonts.
    /// </summary>
    public byte[] GetFont(string faceName)
    {
        switch (faceName)
        {
            case "Janitor#":
                return DemoFontHelper.Janitor;
            case "Ubuntu#":
                return DemoFontHelper.Ubuntu;
            case "Ubuntu#b":
                return DemoFontHelper.UbuntuBold;
            case "Ubuntu#i":
                return DemoFontHelper.UbuntuItalic;
            case "Ubuntu#bi":
                return DemoFontHelper.UbuntuBoldItalic;
        }
        return GetFont(faceName);
    }
}
/// <summary>
/// Helper class that reads font data from embedded resources.
/// </summary>
public static class DemoFontHelper
{
    public static byte[] Janitor
    {
        get { return LoadFontData("RealEstateDocumentGenerator.fonts.janitor.Janitor.ttf"); }
    }
    // Tip: I used JetBrains dotPeek to find the names of the resources (just look how dots in folder names are encoded).
    // Make sure the fonts have compile type "Embedded Resource". Names are case-sensitive.
    public static byte[] Ubuntu
    {
        get { return LoadFontData("RealEstateDocumentGenerator.fonts.ubuntufontfamily0._80.Ubuntu-B.ttf"); }
    }
    public static byte[] UbuntuBold
    {
        get { return LoadFontData("RealEstateDocumentGenerator.fonts.ubuntufontfamily0._80.Ubuntu-B.ttf"); }
    }
    public static byte[] UbuntuItalic
    {
        get { return LoadFontData("RealEstateDocumentGenerator.fonts.ubuntufontfamily0._80.Ubuntu-RI.ttf"); }
    }
    public static byte[] UbuntuBoldItalic
    {
        get { return LoadFontData("RealEstateDocumentGenerator.fonts.ubuntufontfamily0._80.Ubuntu-BI.ttf"); }
    }
    /// <summary>
    /// Returns the specified font from an embedded resource.
    /// </summary>
    static byte[] LoadFontData(string name)
    {
        var assembly = Assembly.GetExecutingAssembly();
        using (Stream stream = assembly.GetManifestResourceStream(name))
        {
            if (stream == null)
                throw new ArgumentException("No resource with name " + name);
            int count = (int)stream.Length;
            byte[] data = new byte[count];
            stream.Read(data, 0, count);
            return data;
        }
    }
}

家庭控制器:

public class HomeController : Controller
{
    [HttpPost]
    public ActionResult CreateDocument()
    {
        DemoProjectMain();
        return View();
    }
    public void DemoProjectMain()
    {
        // That's all it takes to register your own fontresolver
        GlobalFontSettings.FontResolver = new DemoFontResolver();
        // And now the slightly modified MigraDoc Hello World sample.
        // Create a MigraDoc document
        Document document = DemoCreateDocument();
        document.UseCmykColor = true;
        // Create a renderer for the MigraDoc document.
        PdfDocumentRenderer pdfRenderer = new PdfDocumentRenderer(unicode);
        WriteDocument(document, pdfRenderer);
    }
    public void WriteDocument(Document document, PdfDocumentRenderer renderer)
    {
        renderer.Document = document;
        renderer.RenderDocument();
        // Send PDF to browser
        MemoryStream stream = new MemoryStream();
        renderer.PdfDocument.Save(stream, false);
        Response.Clear();
        Response.ContentType = "application/pdf";
        Response.AddHeader("content-length", stream.Length.ToString());
        Response.BinaryWrite(stream.ToArray());
        Response.Flush();
        stream.Close();
        Response.End();
    }
    /// <summary>
    /// Creates an absolutely minimalistic document.
    /// </summary>
    static Document DemoCreateDocument()
    {
        // Create a new MigraDoc document
        Document document = new Document();
        DemoSetupStyles(document);
        // Add a section to the document
        Section section = document.AddSection();
        // Add a paragraph to the section
        Paragraph paragraph = section.AddParagraph();
        paragraph.Format.Font.Color = Color.FromCmyk(100, 30, 20, 50);
        // Add some text to the paragraph
        paragraph.AddFormattedText("Hello, World!", TextFormat.Bold);
        section.AddParagraph("Hello, World!");
        // Demonstration for Heading styles.
        paragraph = section.AddParagraph("Hello, World! (Heading 1)");
        paragraph.Style = StyleNames.Heading1;
        paragraph = section.AddParagraph("Hello, World! (Heading 2)");
        paragraph.Style = StyleNames.Heading2;
        paragraph = section.AddParagraph("Hello, World! (Heading 3)");
        paragraph.Style = StyleNames.Heading3;
        paragraph = section.AddParagraph("Hello, World! (Heading 4)");
        paragraph.Style = StyleNames.Heading4;
        paragraph = section.AddParagraph();
        paragraph.Format.Font.Color = Color.FromCmyk(100, 30, 20, 50);
        // Add some text to the paragraph
        paragraph.AddFormattedText("Hello, World!", TextFormat.Bold);
        section.AddParagraph("Hello, World!");
        return document;
    }
    private static void DemoSetupStyles(Document document)
    {
        // Default font for all styles.
        var style = document.Styles[StyleNames.Normal];
        style.Font.Name = "Ubuntu";
        // Overwrite font for headings 1 & 2.
        style = document.Styles[StyleNames.Heading1];
        style.Font.Name = "Janitor";
        style.Font.Size = 32;
        // Heading 2 inherits font from Heading 1.
        style = document.Styles[StyleNames.Heading2];
        style.Font.Size = 28;
        // Set normal font for Heading 3.
        style = document.Styles[StyleNames.Heading3];
        style.Font.Name = "Ubuntu";
        style.Font.Size = 24;
        style = document.Styles[StyleNames.Heading4];
        style.Font.Size = 20;
    }
}

当我运行应用程序并单击触发演示代码的按钮时,我得到一个错误"字体'Ubuntu'找不到",发生在renderer.RenderDocument()中。我如何让字体解析器找到/识别字体,这样我就可以使用MigraDoc在我的ASP上生成pdf。. NET MVC应用程序?

完整的错误信息和堆栈跟踪如下:

'/'应用程序服务器错误。

字体无法找到Ubuntu。

描述:在执行过程中发生未处理的异常当前的web请求。请查看堆栈跟踪了解更多信息有关错误及其在代码中的起源的信息。

Exception Details: System。字体'Ubuntu'不能是发现。

源错误:

Line 305:
Line 306:            renderer.Document = document;
Line 307:            renderer.RenderDocument();
Line 308:
Line 309:            // Send PDF to browser

源文件:C:'Users'User'Documents'Visual Studio 2015'Projects'DocumentGenerator'DocumentGenerator'Controllers'HomeController.cs行:307

堆栈跟踪:

[ArgumentException: Font 'Ubuntu' cannot found.]

System.Drawing.FontFamily.CreateFontFamily(String name, FontCollection fontCollection) +1123173
System.Drawing.FontFamily..ctor(String name) +11
PdfSharp.Drawing.XFontFamily..ctor(String name) +92
MigraDoc.Rendering.FontHandler.GetDescent(XFont font) +129
MigraDoc.Rendering.ParagraphRenderer.CalcVerticalInfo(XFont font) +154
MigraDoc.Rendering.ParagraphRenderer.InitFormat(Area area, FormatInfo previousFormatInfo) +392
MigraDoc.Rendering.ParagraphRenderer.Format(Area area, FormatInfo previousFormatInfo) +62
MigraDoc.Rendering.TopDownFormatter.FormatOnAreas(XGraphics gfx, Boolean topLevel) +738
MigraDoc.Rendering.FormattedDocument.Format(XGraphics gfx) +647
MigraDoc.Rendering.DocumentRenderer.PrepareDocument() +269
MigraDoc.Rendering.PdfDocumentRenderer.PrepareDocumentRenderer(Boolean prepareCompletely) +119
MigraDoc.Rendering.PdfDocumentRenderer.PrepareRenderPages() +19
MigraDoc.Rendering.PdfDocumentRenderer.RenderDocument() +13
DocumentGenerator.Controllers.HomeController.WriteDocument(Document document, PdfDocumentRenderer renderer) in C:'Users'User'Documents'Visual Studio 2015'Projects'DocumentGenerator'DocumentGenerator'Controllers'HomeController.cs:307
DocumentGenerator.Controllers.HomeController.DemoProjectMain() in C:'Users'User'Documents'Visual Studio 2015'Projects'DocumentGenerator'DocumentGenerator'Controllers'HomeController.cs:165
DocumentGenerator.Controllers.HomeController.CreateDocument(CreateDocumentViewModel model, String command) in C:'Users'User'Documents'Visual Studio 015'Projects'DocumentGenerator'DocumentGenerator'Controllers'HomeController.cs:56
lambda_method(Closure , ControllerBase , Object[] ) +146
System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters) +14
System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters) +157
System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters) +27
System.Web.Mvc.Async.AsyncControllerActionInvoker.<BeginInvokeSynchronousActionMethod>b__39(IAsyncResult asyncResult, ActionInvocation innerInvokeState) +22
System.Web.Mvc.Async.WrappedAsyncResult`2.CallEndDelegate(IAsyncResult asyncResult) +29
System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +49
System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethod(IAsyncResult asyncResult) +32
System.Web.Mvc.Async.AsyncInvocationWithFilters.<InvokeActionMethodFilterAsynchronouslyRecursive>b__3d() +50
System.Web.Mvc.Async.<>c__DisplayClass46.<InvokeActionMethodFilterAsynchronouslyRecursive>b__3f() +225
System.Web.Mvc.Async.<>c__DisplayClass33.<BeginInvokeActionMethodWithFilters>b__32(IAsyncResult asyncResult) +10
System.Web.Mvc.Async.WrappedAsyncResult`1.CallEndDelegate(IAsyncResult asyncResult) +10
System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +49
System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethodWithFilters(IAsyncResult asyncResult) +34
System.Web.Mvc.Async.<>c__DisplayClass2b.<BeginInvokeAction>b__1c() +26
System.Web.Mvc.Async.<>c__DisplayClass21.<BeginInvokeAction>b__1e(IAsyncResult asyncResult) +100
System.Web.Mvc.Async.WrappedAsyncResult`1.CallEndDelegate(IAsyncResult asyncResult) +10
System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +49
System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeAction(IAsyncResult asyncResult) +27
System.Web.Mvc.Controller.<BeginExecuteCore>b__1d(IAsyncResult asyncResult, ExecuteCoreState innerState) +13
System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +29
System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +49
System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) +36
System.Web.Mvc.Controller.<BeginExecute>b__15(IAsyncResult asyncResult, Controller controller) +12
System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +22
System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +49
System.Web.Mvc.Controller.EndExecute(IAsyncResult asyncResult) +26
System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.EndExecute(IAsyncResult asyncResult) +10
System.Web.Mvc.MvcHandler.<BeginProcessRequest>b__5(IAsyncResult asyncResult, ProcessRequestState innerState) +21
System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +29
System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +49
System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +28  
System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) +9
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +9723757
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155

版本信息:Microsoft .NET Framework Version:4.0.30319;ASP。净版:4.6.79.0

用于嵌入式字体的PDFsharp / MigraDoc字体解析器:System.ArgumentException: F

您正在使用GDI构建的MigraDoc。错误信息来自GDI+。

我的示例代码是用WPF构建测试的。请在您的服务器上试用WPF版本。

我猜你仍然必须使用XPrivateFontCollection与GDI构建。如果你想在你的服务器上坚持GDI构建,删除IFontResolver并使用XPrivateFontCollection。