我正在使用MigraDoc在我的ASP.NET5 MVC6 Web應用程序中生成PDF,該應用程序已部署到Azure雲。我使用的是1.50版本的beta-2,但我也嘗試使用v1.50 beta-1和v1.32。用於嵌入字體的PDFsharp/MigraDoc字體解析器:System.ArgumentException:字體'Ubuntu'無法找到
我已經在應用程序在本地運行時生成PDF。但是,當應用程序在雲服務器上運行時,由於無法訪問任何字體,導致生成PDF時遇到了很大的麻煩。 Following the PDFsharp docs,我試圖通過在我的代碼中嵌入字體來創建「私人字體」。
我對使用PDFsharp直接
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,這樣我就不必做所有的排版自己的雲計算成功生成PDF文件。
我遵循ThomasHövel的博客here (this is the new one for beta-2的優秀指南,儘管我之前也曾遵循過his earlier post for beta-1)。他的項目在當地是完全適合我的。
我實現了用於我的Web App項目的示例。這是正是相同,只是main
托馬斯的代碼是在我的控制器的方法是點擊一個按鈕運行:
字體Resolver類:
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;
}
}
}
Home控制器:
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;
}
}
當我運行該應用程序並單擊觸發演示代碼的按鈕時,出現錯誤「Font '找不到'在renderer.RenderDocument()發生。 如何獲取字體解析器以查找/識別字體,以便我可以使用MigraDoc在ASP.NET MVC應用程序上生成PDF文件?
完整的錯誤消息和堆棧跟蹤如下:
Server Error in '/' Application.
Font 'Ubuntu' cannot be found.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.ArgumentException: Font 'Ubuntu' cannot be found.
Source Error:
Line 305: Line 306: renderer.Document = document; Line 307: renderer.RenderDocument(); Line 308: Line 309: // Send PDF to browser
Source File: C:\Users\User\Documents\Visual Studio 2015\Projects\DocumentGenerator\DocumentGenerator\Controllers\HomeController.cs Line: 307
Stack Trace:
[ArgumentException: Font 'Ubuntu' cannot be 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
Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.6.79.0
錯誤發生在第307行'renderer.RenderDocument();'中。您顯示的HomeController源代碼包含'pdfRenderer.RenderDocument();'行。也許你正在運行的代碼不是你想運行的代碼 - 至少它不是你在這裏展示的代碼。很難找到錯誤。 –
嗨@ThomasH - 你說的對,我很抱歉。實際上,我將添加到示例中的代碼移到了一個單獨的'WriteDocument'方法中,以更清楚地將其隔離。我已經更新了顯示此代碼的代碼,您可以希望看到現在在該方法中的「Line 307:renderer.RenderDocument();」的位置。 – Ivan