HTML to PDF conversion fails on Linux - font not found

I’m performing HTML to PDF conversion on an Azure Function app running .NET 8 on Linux. The process always fails. The following message appears:

No font was found. To resolve this problem, you can set up your custom set of fonts, following this documentation article: Font Folder – How to Install using Aspose.HTML for .NET

This seems to refer to classes found in Aspose.HTML, which we do not have. We are using Aspose.PDF.Drawing library (latest).
On Azure function apps, there is no way to install fonts. I tried this:
FontRepository.Sources.Add(new MemoryFontSource(bytes));
But it doesn’t seem to matter.

Is there any supported way to work around this problem?

@vladigubler

Cause

The error message you’re encountering indicates that the required fonts are not available in your Azure Function app environment. This is a common issue when converting HTML to PDF on Linux, especially when the fonts used in the HTML are not installed or accessible.

Solution

Since you cannot install fonts directly on Azure Functions, you can use a workaround by embedding the fonts directly into your application. This can be done by loading the font files from memory or a specific location within your application.

Here’s how you can do it:

  1. Load Fonts from Memory: If you have the font files available, read them into a byte array and then use MemoryFontSource to add them to the FontRepository.

  2. Set Up HtmlLoadOptions: Ensure that you are using HtmlLoadOptions to specify that fonts should be embedded.

Code

Here’s a sample code snippet demonstrating how to load fonts from memory and set up the HTML to PDF conversion:

using Aspose.Pdf;
using Aspose.Pdf.Text;
using System.IO;

// Load your font file into a byte array
byte[] fontBytes = File.ReadAllBytes("path/to/your/font.ttf");

// Add the font to the FontRepository
FontRepository.Sources.Add(new MemoryFontSource(fontBytes));

// Set up HtmlLoadOptions
HtmlLoadOptions options = new HtmlLoadOptions
{
    IsEmbedFonts = true // Ensure fonts are embedded
};

// Convert HTML to PDF
using (Document pdfDocument = new Document("path/to/your/input.html", options))
{
    pdfDocument.Save("path/to/your/output.pdf");
}

Next Steps

  1. Ensure that the font files you are using are licensed for embedding.
  2. Test the conversion after implementing the above code to confirm that the fonts are correctly applied.
  3. If you encounter any further issues, check the logs for more detailed error messages.

Please implement these changes and let me know if you need any further assistance!

Unfortunately, it doesn’t help. I can see that the font is read from the embedded resources, the byte array length is correct and the MemoryFontSource is successfully added to the repository. I still get the same error on the constructor call of Document class.

BTW, I create Document from HTML string, not file path, but I would assume it doesn’t matter.

@vladigubler

Would you kindly share your sample code snippet with sample HTML string for our reference? We will test the scenario in our environment and address it accordingly.

Here you go:

public class Convert
{
    private readonly ILogger<Convert> _logger;

    public Convert(ILogger<Convert> logger)
    {
        _logger = logger;
    }

    [Function("Convert")]
    public IActionResult Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequest req)
    {
        _logger.LogInformation("C# HTTP trigger function processed a request.");

        try
        {
            var content = "<html><head><style>.a{font-family: Arial;font-size:24px}</style></head><body><div class='a'>Hello</div></body></html>";

            var assembly = Assembly.GetExecutingAssembly();
            using (var fs = assembly.GetManifestResourceStream("TestPDFFunc.Fonts.ARIAL.TTF"))
            {
                var fms = new MemoryStream();
                fs.CopyTo(fms);
                var bytes = fms.ToArray();
                var s = new MemoryFontSource(bytes);
                FontRepository.Sources.Add(s);
            }

            var options = new HtmlLoadOptions();
            options.IsEmbedFonts = true;

            using (var outputStream = new MemoryStream())
            {
                using (var ms = new MemoryStream())
                {
                    var writer = new StreamWriter(ms);
                    writer.Write(content);
                    writer.Flush();
                    ms.Position = 0;

                    using (var pdfDocument = new Aspose.Pdf.Document(ms, options))
                    {
                        pdfDocument.Info.Title = "Test one";
                        pdfDocument.Save(outputStream);
                    }
                }

                outputStream.Position = 0;

                return new FileContentResult(outputStream.ToArray(), "application/pdf")
                {
                    FileDownloadName = "myfile.pdf"
                };
            }
        }
        catch (Exception ex)
        {
            var res = new ContentResult();
            res.Content = ex.ToString();
            res.StatusCode = 500;
            return res;
        }

    }
}

You can also try out this test function at this URL:
https://infowiseaction2eastus-test-h0e6bhdrdcgpf9c9.eastus-01.azurewebsites.net/api/Convert

I added the ARIAL.TTF file to Fonts folder in the project and made it an embedded resource.

@vladigubler

We are checking it and will get back to you shortly.

@vladigubler

We have opened the following new ticket(s) in our internal issue tracking system and will deliver their fixes according to the terms mentioned in Free Support Policies.

Issue ID(s): PDFNET-60293

You can obtain Paid Support Services if you need support on a priority basis, along with the direct access to our Paid Support management team.

Am I going to be automatically notified when it’s resolved? It’s not extremely urgent at this point to justify paid support, but I would love to see it resolved within a reasonable timeframe.

@vladigubler

Yes, you will be receiving a notification via this forum thread once the ticket is resolved. It will be prioritized on a first-come, first-served basis as per free support policies. We will also keep you posted with ticket status here. Please spare us some time.

1 Like