HakanL / WkHtmlToPdf-DotNet

C# .NET Core wrapper for wkhtmltopdf library that uses Webkit engine to convert HTML pages to PDF.
GNU Lesser General Public License v3.0
372 stars 67 forks source link

Dependency error calling Convert method executing Lambda #66

Closed ReuvenT closed 2 years ago

ReuvenT commented 2 years ago

Hi,

First of all, thanks very much for putting this code together. I'm working on upgrading a working .Net Core 2.1 lambda with DinkToPdf to 3.1 and struggling with dependencies, hoping this code is easier. But still running into issues with dependencies. Specifically, this error when trying to convert the html to byte[]:

Exception encountered on server. System.AggregateException: One or more errors occurred. (Unable to load native library. The platform may be missing native dependencies (libjpeg62, etc). Or the current platform is not supported.)

Pretty sure the issue is with the deployment / package, rather than the code. Here is the command I use to manually build the uploaded zip file: dotnet lambda package --configuration debug --framework netcoreapp3.1 --output-package bin/Release/netcoreapp3.1/release.zip

And attached is the csproj fil VDEx.FCRA.WebAPI.csproj,txt e

Any suggestions? Thanks, Reuven

ReuvenT commented 2 years ago

One other note - the code that does the conversion to PDF works as expected in the unit tests, i.e. locally in Visual Studio.

HakanL commented 2 years ago

Most likely the lambda environment (I assume this is AWS Lambda) doesn't allow the execution of native libraries (or it may require special commands to prep the environment with the native dependencies). I'm not very familiar with AWS Lambda though.

ReuvenT commented 2 years ago

I just saw issue https://githubmemory.com/repo/HakanL/WkHtmlToPdf-DotNet/issues/48 which seems to be related as well. I posted a support case with AWS with this question too. Let me know if there are other users (of AWS lambda) that have had success that I can learn from.

HakanL commented 2 years ago

Are you using a docker image in Lambda?

ReuvenT commented 2 years ago

DevOps does have a docker workflow, but I'm working on POC, and deploying publish package directly. See question. Details above. If you have details to resolve this using Dpcker, I'd be interested.

HakanL commented 2 years ago

The solution includes a docker sample project that you can look at.

ReuvenT commented 2 years ago

Hi Hankan, Still trying to resolve this reference issue running the code in a lambda image - error:

ComposeReportService.ConvertToPdf Exception encountered on server. System.AggregateException: One or more errors occurred. (Unable to load native library. The platform may be missing native dependencies (libjpeg62, etc). Or the current platform is not supported.) ---> System.NotSupportedException: Unable to load native library. The platform may be missing native dependencies (libjpeg62, etc). Or the current platform is not supported. at WkHtmlToPdfDotNet.ModuleFactory.GetModule() at WkHtmlToPdfDotNet.PdfTools.Load() at WkHtmlToPdfDotNet.BasicConverter.Convert(IDocument document) at WkHtmlToPdfDotNet.SynchronizedConverter.<>n0(IDocument document) at WkHtmlToPdfDotNet.SynchronizedConverter.<>cDisplayClass4_0.b0() at System.Threading.Tasks.Task`1.InnerInvoke() at System.Threading.Tasks.Task.<>c.<.cctor>b274_0(Object obj) at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state) --- End of stack trace from previous location where exception was thrown --- at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread) --- End of inner exception stack trace --- at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken) at System.Threading.Tasks.Task.Wait() at WkHtmlToPdfDotNet.SynchronizedConverter.Invoke[TResult](Func`1 delegate) at WkHtmlToPdfDotNet.SynchronizedConverter.Convert(IDocument document)

I've tried multiple variations on the Dokerfile and csproj, but still can't see, to get the components lined up. I've also expanded the image (tar) to see if the libjpeg62 is anywhere in the image folders - it's not. Attached are the csproj and Dockerfile from my current testing. csproj and Dockerfile.zip

Any suggestions? (I've also opened a ticket with AWS support to see if they have any suggestions). The PDFs are created successfully running the unit test in my code.

Thanks, Reuven

HakanL commented 2 years ago

So the missing dependencies are native libraries, meaning they are not .NET dependencies that would be installed via the csproj file but instead have to be installed in your Linux environment using apt-get/rpm. Have you tried the docker sample that's in the project, is it working? The native libraries for wkhtmltopdf (which we just embed, we're not creating those) don't include those dependencies (that's why they are called dependencies), they have to be available in the environment for the wkhtmltopdf native library to load. When you run the unit tests those are running on your development machine, not in docker, so that's very different.

ReuvenT commented 2 years ago

No, I haven't installed the sample (not clear what project to build/deploy on https://github.com/HakanL/WkHtmlToPdf-DotNet). I understand the concepts, it's the mechanics that I'm stuck on. Because this is deployed to a lambda, there are other components that AWS requires, which make it hard to use your Dockerfile as is. I've attached mine above that works fine except for this dependency error.

In the project page here there is a confusing note: "Note that with this NuGet package you don't need to manually add the native binaries to your project." How does that relate to the inclusion of the apt-get install instruction in the sample's Dockerfile - which I use as well. Another question about the mechanics - the apt-get install refers to libjpeg62-turbo, and the error message complains about libjpeg62 - is the "turbo" part a spoiler?

Thanks, Reuven

HakanL commented 2 years ago

Ok, yeah under samples there's a docker project named TestConsoleAppDocker, try to run that as-is to make sure your docker environment is good. That way you can perhaps use that as a template as well and make small changes until it works in your project. Don't read too much into the error message about libjpeg62, it's not a generated message that says libjpeg is missing, it's just a suggestion that dependencies are missing, and the most common is libjpeg that's why I wrote that in the error message to help people. But the .NET wrapper has no way of knowing exactly which library is missing, it just fails to load the native library. There are 3 parts:

This project only includes the first 2 out of this list. And you get the above error when anything from the last part is missing, but it can't tell exactly what is missing, just that it can't load the native library (part 2 above) successfully. So there's no way this wrapper project can determine or even include any of these dependencies, since they are all native. If you can get a docker to run locally then you're at a much higher chance to get it to run in AWS.

ReuvenT commented 2 years ago

Hi,

I've done some additional testing, and hope with this information, I can resole the issue. The TestConsoleAppDocker runs successfully in the container. I've included in this solution my lambda project referencing the WkHtmlToPdf-DotNet and built a container, and deployed to AWS lambda with LD_DEBUG env set to all. There is an exception thrown, and it looks like libjpeg.so.62 is the missing component. cloudwatch log is attached together with the docker file used to create the lambda container. Dockerfile.zip

So in this solution there is one project, a console app, that successfully executes, and a second project, a lambda, fails to generate the pdf. I suspect that the base builds in the lambda docker do not contain the required dependency. That is my question - how can I build the container for a lambda deployment that contains the required dependencies.

Thanks, Reuven

HakanL commented 2 years ago

I think you've done a good job figuring out what's missing. Typically you'd update the dockerfile to install the missing dependencies, but there may be other sub-dependencies so the best way is to login to the container and try to manually install all the dependencies, look at errors and write down what's needed. Then you update your dockerfile to reflect what you had to do manually. I'm sure there are other ways, but that's what I've done in the past. It's some trial and error, but I want to stress that it's not related to this .NET wrapper at all, this is just normal docker tasks.

ReuvenT commented 2 years ago

Stackoverflow https://stackoverflow.com/questions/70525819/how-to-resolve-libwkhtmltox-so-reference-in-net-aws-lambda-docker-image has a response that may be helpful. This project was transferred to another developer, and was resolved with that post. Closing the issue.