Aspose.PDF / AWS Lambda C# runtime

I am attempting to use Aspose.PDF in an AWS Lambda environment. I have the following handler defined:

public class PdfUtils
{
   public Response FlattenPdfForm(Request request)
   {
       WithObject(request.PdfKey, (pdf) =>
       {
           var document = new Document(pdf);
           document.Form.Type = FormType.Standard;
           document.Save("flattened.aspose.pdf");
       });

       return new Response("Go Serverless v1.0! Your function executed successfully!", request);
   }

   private void WithObject(string key, Action<string> action)
   {
       using var s3 = new AmazonS3Client();
       using var pdfResponse = s3.GetObjectAsync(new GetObjectRequest { BucketName = BucketName, Key = key });
       pdfResponse.Wait();

       var pdf = Path.GetTempFileName();

       try
       {
           pdfResponse.Result.WriteResponseStreamToFileAsync(pdf, false, default(System.Threading.CancellationToken)).Wait();
           action(pdf);
       }
       finally
       {
           File.Delete(pdf);
       }
   }

   private string BucketName => Environment.GetEnvironmentVariable("S3_BUCKET_NAME");
}

When it runs, it seems to not like the document.Form.Type = FormType.Standard line and it bags with the following exception:

{
  "errorType": "NullReferenceException",
  "errorMessage": "Object reference not set to an instance of an object.",
  "stackTrace": [
    "at #=z2rshOQYLk8j6LcibgDCnJpx28yCTsFI_C4RCuTw=..ctor(FontCollection #=zbpJ5jZ01eRJL, #=zmQ2IzQQuwJuzpkkhGQkD9qLkjs6dVhmEmA== #=z0AOheY$$hzFL00GNVg==)",
    "at Aspose.Pdf.Forms.Form.#=zvzcuW4Rrz3IejRx3w3uWOIg=(String #=z0hyUue80LjHvYl_jzed_NbM=, String #=zau2CIZoWdQDMkWXapQ==, String #=zAjVfsl__S$HzdzslXw==)",
    "at Aspose.Pdf.Forms.Form.set_Type(FormType value)",
    "at AwsDotnetCsharp.PdfUtils.<>c.<FlattenPdfForm>b__0_0(String pdf) in /builds/Y2o-xFcH/0/pdf-utils/PdfUtils.cs:line 21",
    "at AwsDotnetCsharp.PdfUtils.WithObject(String key, Action`1 action) in /builds/Y2o-xFcH/0/pdf-utils/PdfUtils.cs:line 40",
    "at AwsDotnetCsharp.PdfUtils.FlattenPdfForm(Request request) in /builds/Y2o-xFcH/0/pdf-utils/PdfUtils.cs:line 18",
    "at lambda_method(Closure , Stream , Stream , LambdaContextInternal )"
  ]
}

I’m guessing that it has something to do with the FontCollection line in that it can’t find certain fonts? Is there some base level of fonts that need to be made available for this to work in a lambda environment?

Thanks in advance.

@leviwilson

We recommend installing Windows Core Fonts (Windows Essential Fonts) in your system while working with PDF documents. However, if you are still facing the issue after installing the fonts, please share your sample PDF document with us so that we can test the scenario in our environment and address it accordingly.

Thanks for the response. I was able to get it working within a docker container; now I just need to put those fonts in a lambda layer or something I think.

My next issue is that Aspose.PDF seems to scrunch all the text together. iText seems to handle it fine. Is there a reason that might be?

I have gone ahead and attached the original document, the Aspose.PDF result as well as the iText result from their trial. I should not that I did this conversion on OSX as well as Windows and it yields the same result with Aspose.PDF.

original.pdf (248.5 KB)
output.aspose.pdf (834.3 KB)
output.itext.pdf (201.0 KB)

@asad.ali I thought that I had this working, but it seems that I’m still unable to get the fonts configured in this AWS Lambda environment.

Originally it seems to blow up like my original question if you do NOT do a FontRepository.Sources.Add giving it something that can find fonts. When I added a directory that had .ttf files in it, that seemed to get past it.

After that I was fighting with getting libgdiplus appropriately configured in the AWS Lambda environment, but I eventually got past that with a lambda layer.

Now I’m still struggling with getting it to find fonts.

I created a fonts directory and put all of the fonts from another Windows system in there from C:\Windows\fonts. To test / simulate the AWS Lambda environment I’m using the following:

docker run --rm -it -v $PWD:/sandbox -w /sandbox lambci/lambda:20201112-build-dotnetcore3.1 /bin/bash

Once in there, I have to set LD_LIBRARY_PATH so I can make libgdiplus available.

$ LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/sandbox/layers/libgdiplus/lib
$ PATH=$PATH:/sandbox/layers/libgdiplus/bin

To test my function I’m just simply doing a dotnet run. Here is my routine that I’m testing:

       private static void Main(string[] args)
       {
           var license = new License();
           license.SetLicense("Aspose.Pdf.csharp.lic");
           var document = new Document("xfa_filled.pdf");
           document.Form.Type = FormType.Standard;
           document.Save("flattened.aspose.pdf");
       }

So the first time you dotnet run here, you’ll get my original error:

ash-4.2# dotnet run
Unhandled exception. System.NullReferenceException: Object reference not set to an instance of an object.
   at #=z2rshOQYLk8j6LcibgDCnJpx28yCTsFI_C4RCuTw=..ctor(FontCollection #=zbpJ5jZ01eRJL, #=zmQ2IzQQuwJuzpkkhGQkD9qLkjs6dVhmEmA== #=z0AOheY$$hzFL00GNVg==)
   at Aspose.Pdf.Forms.Form.#=zvzcuW4Rrz3IejRx3w3uWOIg=(String #=z0hyUue80LjHvYl_jzed_NbM=, String #=zau2CIZoWdQDMkWXapQ==, String #=zAjVfsl__S$HzdzslXw==)
   at Aspose.Pdf.Forms.Form.set_Type(FormType value)
   at AwsDotnetCsharp.PdfUtils.Main(String[] args) in /sandbox/PdfUtils.cs:line 22

This now requires you to to add the following line:

FontRepository.Sources.Add(new FolderFontSource("/sandbox/msfonts")); // from c:\windows\fonts

Once adding that now you’ll get the following:

bash-4.2# dotnet run
Fontconfig error: Cannot load default config file
Unhandled exception. System.TypeInitializationException: The type initializer for '#=zxi2oiph7E_QrSuk4FyBC7Vo=' threw an exception.
 ---> System.ArgumentException: Font '?' cannot be found.
   at System.Drawing.SafeNativeMethods.Gdip.CheckStatus(Int32 status)
   at System.Drawing.FontFamily.GetGdipGenericSansSerif()
   at System.Drawing.FontFamily.get_GenericSansSerif()
   at System.Drawing.Font.CreateFont(String familyName, Single emSize, FontStyle style, GraphicsUnit unit, Byte charSet, Boolean isVertical)
   at System.Drawing.Font..ctor(String familyName, Single emSize, FontStyle style, GraphicsUnit unit, Byte gdiCharSet, Boolean gdiVerticalFont)
   at System.Drawing.Font..ctor(String familyName, Single emSize, String systemName)
   at System.Drawing.SystemFonts.get_DefaultFont()
   at #=zs0HZcWyJMF6QVJnacXvhuXq5u8TC.#=zi4B5ghRwkaRe()
   at #=zDxN2KO_gFVoQOlvsVKTX2IzoFHxV.#=z2Ul_ohf_ETfq(String #=zqTiGoxc=, FontStyle #=zKnLz$18=, String #=z6Q_S19KrKRMr)
   at #=zDxN2KO_gFVoQOlvsVKTX2IzoFHxV.#=zBECmHXmvWXhm(String #=zqTiGoxc=, Single #=zc5R8OOSA0Npt, FontStyle #=zKnLz$18=, String #=z6Q_S19KrKRMr)
   at #=zDxN2KO_gFVoQOlvsVKTX2IzoFHxV.#=zBECmHXmvWXhm(String #=zqTiGoxc=, Single #=zc5R8OOSA0Npt, FontStyle #=zKnLz$18=)
   at #=zxi2oiph7E_QrSuk4FyBC7Vo=..cctor()
   --- End of inner exception stack trace ---
   at #=zxi2oiph7E_QrSuk4FyBC7Vo=..ctor(PointF #=zQqrH5so=, String #=zO7PsOj0=, SizeF #=zDMIZvYg=, Boolean #=znB7xfXqZ88Cb)
   at #=zNu0IYqfxsWx2JVHV_g5HBjBrYvH8UblDtSoSA9U=.#=zSCwT2Do=(#=zrLgNkPePdgvkxIvamT438vMyQnhiPCd1Kg== #=zJS1FR_4=, XmlNode #=zYyovubM=)
   at #=zMd93ULWdFZfAmF9ilFPW$TUis3EHPY7Rqg==.#=zSCwT2Do=(#=zrLgNkPePdgvkxIvamT438vMyQnhiPCd1Kg== #=zJS1FR_4=, XmlNode #=zXGtb6kI=, #=z1JZuFYvOARS2SB2Yo7LY0j$Szk1e #=zprqRCoo=)
   at #=zNB9TpMtC4hr1l8nt2F$tMwBKSugRnDYeavzjB1c=.#=zSCwT2Do=(#=zrLgNkPePdgvkxIvamT438vMyQnhiPCd1Kg== #=zJS1FR_4=, XmlNode #=zYyovubM=)
   at #=zlOJsHZYIDrpPC4nxlyV2ZoIaOtrHRdXL4Q==.#=zSCwT2Do=(#=zrLgNkPePdgvkxIvamT438vMyQnhiPCd1Kg== #=zJS1FR_4=, XmlNode #=zYyovubM=)
   at #=zusO7XRyLVGafakVu8YwhmhcSgAXczv7h5DkAj0U=.#=zSCwT2Do=(#=zrLgNkPePdgvkxIvamT438vMyQnhiPCd1Kg== #=zJS1FR_4=, XmlNode #=zYyovubM=)
   at #=zlOJsHZYIDrpPC4nxlyV2ZoIaOtrHRdXL4Q==.#=zSCwT2Do=(#=zrLgNkPePdgvkxIvamT438vMyQnhiPCd1Kg== #=zJS1FR_4=, XmlNode #=zYyovubM=)
   at #=zlOJsHZYIDrpPC4nxlyV2ZoIaOtrHRdXL4Q==.#=zSCwT2Do=(#=zrLgNkPePdgvkxIvamT438vMyQnhiPCd1Kg== #=zJS1FR_4=, XmlNode #=zYyovubM=)
   at #=zlOJsHZYIDrpPC4nxlyV2ZoIaOtrHRdXL4Q==.#=zSCwT2Do=(#=zrLgNkPePdgvkxIvamT438vMyQnhiPCd1Kg== #=zJS1FR_4=, XmlNode #=zYyovubM=)
   at #=zlOJsHZYIDrpPC4nxlyV2ZoIaOtrHRdXL4Q==.#=zSCwT2Do=(#=zrLgNkPePdgvkxIvamT438vMyQnhiPCd1Kg== #=zJS1FR_4=, XmlNode #=zYyovubM=)
   at #=zlOJsHZYIDrpPC4nxlyV2ZoIaOtrHRdXL4Q==.#=zSCwT2Do=(#=zrLgNkPePdgvkxIvamT438vMyQnhiPCd1Kg== #=zJS1FR_4=, XmlNode #=zYyovubM=)
   at #=z2rshOQYLk8j6LcibgDCnJigGUrBsrwJz0w==.#=zcSGo4sRJDOq2(Dictionary`2 #=zAQGKTuUki_YA, XfaParserOptions #=z4Gp8a2g=, #=zMirV2avbYCsTZJj7o9Xx4DD7Bf0CVmaMyA== #=z9cbJbqowxnrv, #=z2rshOQYLk8j6LcibgDCnJpx28yCTsFI_C4RCuTw= #=z$uM8DgiOn3AH)
   at #=zA8JgbNdKWulAsBZhVNm$oBDT3RMHxdFFxQ==.#=z0evQ6Lg=(Dictionary`2 #=zAQGKTuUki_YA, XfaParserOptions #=z4Gp8a2g=, #=z2rshOQYLk8j6LcibgDCnJpx28yCTsFI_C4RCuTw= #=z$uM8DgiOn3AH)
   at Aspose.Pdf.Forms.Form.#=zvzcuW4Rrz3IejRx3w3uWOIg=(String #=z0hyUue80LjHvYl_jzed_NbM=, String #=zau2CIZoWdQDMkWXapQ==, String #=zAjVfsl__S$HzdzslXw==)
   at Aspose.Pdf.Forms.Form.set_Type(FormType value)
   at AwsDotnetCsharp.PdfUtils.Main(String[] args) in /sandbox/PdfUtils.cs:line 23

To get past that, in my /sandbox/fonts directory I added a fonts.conf and put this in there:

<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<fontconfig>
  <dir>/sandbox/fonts/</dir>
  <cachedir>/tmp/fonts-cache/</cachedir>
  <include ignore_missing="yes">conf.d</include>
  <config></config>
</fontconfig>

As well set setting FONTCONFIG_PATH=/sandbox/fonts. Now when I fc-list it shows fonts and this gets me past the error where it’s trying to load the System.Drawing.SystemFonts.DefaultFont.

However, now I run into my next error where it blows up saying that it cannot find any system fonts (which is probably true…in an AWS Lambda environment there likely aren’t any system fonts installed)

bash-4.2# dotnet run
Unhandled exception. System.TypeInitializationException: The type initializer for '#=zxi2oiph7E_QrSuk4FyBC7Vo=' threw an exception.
 ---> System.InvalidOperationException: Cannot find any fonts installed on the system.
   at #=zDxN2KO_gFVoQOlvsVKTX2IzoFHxV.#=z2Ul_ohf_ETfq(String #=zqTiGoxc=, FontStyle #=zKnLz$18=, String #=z6Q_S19KrKRMr)
   at #=zDxN2KO_gFVoQOlvsVKTX2IzoFHxV.#=zBECmHXmvWXhm(String #=zqTiGoxc=, Single #=zc5R8OOSA0Npt, FontStyle #=zKnLz$18=, String #=z6Q_S19KrKRMr)
   at #=zDxN2KO_gFVoQOlvsVKTX2IzoFHxV.#=zBECmHXmvWXhm(String #=zqTiGoxc=, Single #=zc5R8OOSA0Npt, FontStyle #=zKnLz$18=)
   at #=zxi2oiph7E_QrSuk4FyBC7Vo=..cctor()
   --- End of inner exception stack trace ---
   at #=zxi2oiph7E_QrSuk4FyBC7Vo=..ctor(PointF #=zQqrH5so=, String #=zO7PsOj0=, SizeF #=zDMIZvYg=, Boolean #=znB7xfXqZ88Cb)
   at #=zNu0IYqfxsWx2JVHV_g5HBjBrYvH8UblDtSoSA9U=.#=zSCwT2Do=(#=zrLgNkPePdgvkxIvamT438vMyQnhiPCd1Kg== #=zJS1FR_4=, XmlNode #=zYyovubM=)
   at #=zMd93ULWdFZfAmF9ilFPW$TUis3EHPY7Rqg==.#=zSCwT2Do=(#=zrLgNkPePdgvkxIvamT438vMyQnhiPCd1Kg== #=zJS1FR_4=, XmlNode #=zXGtb6kI=, #=z1JZuFYvOARS2SB2Yo7LY0j$Szk1e #=zprqRCoo=)
   at #=zNB9TpMtC4hr1l8nt2F$tMwBKSugRnDYeavzjB1c=.#=zSCwT2Do=(#=zrLgNkPePdgvkxIvamT438vMyQnhiPCd1Kg== #=zJS1FR_4=, XmlNode #=zYyovubM=)
   at #=zlOJsHZYIDrpPC4nxlyV2ZoIaOtrHRdXL4Q==.#=zSCwT2Do=(#=zrLgNkPePdgvkxIvamT438vMyQnhiPCd1Kg== #=zJS1FR_4=, XmlNode #=zYyovubM=)
   at #=zusO7XRyLVGafakVu8YwhmhcSgAXczv7h5DkAj0U=.#=zSCwT2Do=(#=zrLgNkPePdgvkxIvamT438vMyQnhiPCd1Kg== #=zJS1FR_4=, XmlNode #=zYyovubM=)
   at #=zlOJsHZYIDrpPC4nxlyV2ZoIaOtrHRdXL4Q==.#=zSCwT2Do=(#=zrLgNkPePdgvkxIvamT438vMyQnhiPCd1Kg== #=zJS1FR_4=, XmlNode #=zYyovubM=)
   at #=zlOJsHZYIDrpPC4nxlyV2ZoIaOtrHRdXL4Q==.#=zSCwT2Do=(#=zrLgNkPePdgvkxIvamT438vMyQnhiPCd1Kg== #=zJS1FR_4=, XmlNode #=zYyovubM=)
   at #=zlOJsHZYIDrpPC4nxlyV2ZoIaOtrHRdXL4Q==.#=zSCwT2Do=(#=zrLgNkPePdgvkxIvamT438vMyQnhiPCd1Kg== #=zJS1FR_4=, XmlNode #=zYyovubM=)
   at #=zlOJsHZYIDrpPC4nxlyV2ZoIaOtrHRdXL4Q==.#=zSCwT2Do=(#=zrLgNkPePdgvkxIvamT438vMyQnhiPCd1Kg== #=zJS1FR_4=, XmlNode #=zYyovubM=)
   at #=zlOJsHZYIDrpPC4nxlyV2ZoIaOtrHRdXL4Q==.#=zSCwT2Do=(#=zrLgNkPePdgvkxIvamT438vMyQnhiPCd1Kg== #=zJS1FR_4=, XmlNode #=zYyovubM=)
   at #=z2rshOQYLk8j6LcibgDCnJigGUrBsrwJz0w==.#=zcSGo4sRJDOq2(Dictionary`2 #=zAQGKTuUki_YA, XfaParserOptions #=z4Gp8a2g=, #=zMirV2avbYCsTZJj7o9Xx4DD7Bf0CVmaMyA== #=z9cbJbqowxnrv, #=z2rshOQYLk8j6LcibgDCnJpx28yCTsFI_C4RCuTw= #=z$uM8DgiOn3AH)
   at #=zA8JgbNdKWulAsBZhVNm$oBDT3RMHxdFFxQ==.#=z0evQ6Lg=(Dictionary`2 #=zAQGKTuUki_YA, XfaParserOptions #=z4Gp8a2g=, #=z2rshOQYLk8j6LcibgDCnJpx28yCTsFI_C4RCuTw= #=z$uM8DgiOn3AH)
   at Aspose.Pdf.Forms.Form.#=zvzcuW4Rrz3IejRx3w3uWOIg=(String #=z0hyUue80LjHvYl_jzed_NbM=, String #=zau2CIZoWdQDMkWXapQ==, String #=zAjVfsl__S$HzdzslXw==)
   at Aspose.Pdf.Forms.Form.set_Type(FormType value)
   at AwsDotnetCsharp.PdfUtils.Main(String[] args) in /sandbox/PdfUtils.cs:line 26

So I’m at a loss in trying to understand how I can get this to work. If I yum install -y dejavu-sans-fonts, it will work. But you can’t do that in a lambda function because you can’t control that. The only way you can control it is via lambda layers (which is what I am using to get the libgdiplus layers as well as the fonts layer).

Please advise.

@leviwilson

Thanks for sharing further details and elaborating on the issue.

Would you please share your sample docker file with us as well so that we can investigate the scenario in particular environment and address it accordingly.

@asad.ali
I put a sample Dockerfile together and it can be found here:

Building / running it should be as easy as:

docker build -t aspose-levi-example . && \
  docker run --rm -it aspose-levi-example

Here is an example output from the GitLab build for it:

@leviwilson

We are looking into it and will get back to you shortly.

I broke this comment (regarding the document differences up above) into a separate thread that can be found here:

Just wanted to keep this one strictly related to the AWS Lambda / fonts issue that I have.

@asad.ali were you able to get anywhere with this? Anything I can help with?

@leviwilson

We regret that we could not determine the cause of the issue yet. Furthermore, we have logged an investigation ticket as PDFNET-49070 in our issue tracking system. We will further analyze this issue (as it seems to be related with fonts path) and let you know as soon as the ticket is resolved. Please be patient and give us some time.

We apologize for the inconvenience.

PS: Please also try to implement this solution if it helps.

@asad.ali the referenced solution is the same one that my sample project is using to point to the fonts.

Even if I Sources.Clear() and reference only the folder source for the fonts, it blows up still saying it can’t find system fonts (exactly as in my example).

@leviwilson

We have updated the information of the logged ticket as we were also able to reproduce the issue in our environment where API threw System.TypeInitializationException even when libgdiplus and windows fonts were installed. We will surely let you know as soon as some updates are available regarding ticket resolution.

We apologize for the inconvenience faced.

1 Like

@asad.ali is there a location where the status of PDFNET-49070 can be tracked? Thanks and have a great Thanksgiving!

@leviwilson

You cannot access the ticket as it is logged in our internal issue management system. However, we will keep you posted about the progress against its resolution within this forum thread.

Hy there !
I use Aspose in a Lambda environment to convert a PDF document to PNG. I have some issues with fonts too.
@leviwilson, have you find a solution to work with Aspose in a Lambda environment ?
@asad.ali, any updates on the PDFNET-49070 ticket ?

Thanks you both in advance

Yes, the solution on my end was to containerize our lambda functions so we had control over them.

It has an added benefit of quicker feedback loops over lambda because I can run them locally.

1 Like

@HelloWork

We are afraid that the earlier logged ticket is not yet resolved. However, we will surely inform you in this forum thread once we have additional updates in this regard.

We apologize for the inconvenience.