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

NotSupportedException with web server inside arm64 container until wkhtmltopdf is installed explicitly #58

Closed ilyahryapko closed 2 years ago

ilyahryapko commented 3 years ago

Hello. Got an issue with workaround when using your library in arm64-hosted containers.

I have Mac M1 and x86 PC. My .net5 containers when launched on each of mentioned devices are arm64 and amd64 (docker specify it by itself i guess). Everything is working fine when containers are x86, but with arm64 the following exception appears `NotSupportedException: Unable to load native library. The platform may be missing native dependencies (libjpeg62, etc). Or the current platform is not supported.

WkHtmlToPdfDotNet.ModuleFactory.GetModule()`

I docker exec-ed into container and tried to investigate the problem. Simple installing the parent library arm64 seems to fix the issue. Installing does not require additional dependencies to be installed, so it's only a matter of parent package itself I guess

I've read in readme that this is not how this library is supposed to function. So I don't know should I stick to that solution. Also I've found repo with binaries, maybe this repo just misses arm64 type of lib? IDK, just guessing.

Some additional info I have following Dockerfile (these packages for install was just copied from output of 'apt install wkhtmltopdf --no-install-recommends', many of them are included in your console app dockerfile).

FROM mcr.microsoft.com/dotnet/aspnet:5.0-buster-slim AS base
WORKDIR /app
COPY ["app/bash", "./"]
EXPOSE 80

RUN apt-get update \
    && apt-get install -y --no-install-recommends \
        ca-certificates \
        fontconfig \
        fontconfig-config \
        fonts-dejavu-core \
        libexpat1 \
        libfontconfig1 \
        libfontenc1 \
        libfreetype6 \
        libjpeg62-turbo \
        libpng16-16 \
        libx11-6 \
        libx11-data \
        libxau6 \
        libxcb1 \
        libxdmcp6 \
        libxext6 \
        libxrender1 \
        lsb-base \
        sensible-utils \
        ucf \
        x11-common \
        xfonts-75dpi \
        xfonts-base \
        xfonts-encodings \
        xfonts-utils

COPY root.crt /usr/local/share/ca-certificates/certificate.crt
RUN update-ca-certificates

# Api
FROM mcr.microsoft.com/dotnet/sdk:5.0-buster-slim AS build
WORKDIR /src
COPY ["app/Api/Api.csproj", "app/Api/"]
RUN dotnet restore "app/Api/Api.csproj"
COPY . .
WORKDIR "/src/app/Api"
RUN dotnet build "Api.csproj" -c Release -o /app/build/Api

FROM build AS publish
RUN dotnet publish "Api.csproj" -c Release -o /app/publish/Api

FROM base AS final
WORKDIR /app/Api
COPY --from=publish /app/publish/Api .

WORKDIR /app
ENTRYPOINT ["/bin/bash", "setup.sh"]

Entrypoint script here only runs dotnet Api.dll

And following csproj (partially presented here)

<PropertyGroup>
    <TargetFramework>net5.0</TargetFramework>
    <DockerComposeProjectPath>..\..\docker-compose.dcproj</DockerComposeProjectPath>
    <DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
    <DockerfileContext>..\..</DockerfileContext>
    <LangVersion>9</LangVersion>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="BCrypt.Net-Core" Version="1.6.0" />
    <PackageReference Include="Google.Apis.Oauth2.v2" Version="1.48.0.1869" />
    <PackageReference Include="Haukcode.WkHtmlToPdfDotNet" Version="1.5.59" />
  //rest imports here
  </ItemGroup>

So is it okay to probably launch some bash script to get current container architecture and install this package if needed? Or solution can be found and commited there? If so I'd like to help with contributing, just need some guidance

ilyahryapko commented 3 years ago

Here's the libraries i've found in container

root@044be08df36e:/app# ldconfig -p | grep 'libwkhtml'
    libwkhtmltox.so.0 (libc6,AArch64) => /usr/local/lib/libwkhtmltox.so.0
    libwkhtmltox.so (libc6,AArch64) => /usr/local/lib/libwkhtmltox.so

https://drive.google.com/file/d/1HYOUanvInomz5giPibU4q2qUaJy8A3II/view?usp=sharing

HakanL commented 3 years ago

@ilyahryapko I haven't added support for ARM64, we need the binaries and probably some additional code. I welcome PRs :)

ilyahryapko commented 3 years ago

@HakanL I will gladly commit that issue, but honestly speaking I do not have any idea on how to start. My first thought was the following algorithm

  1. add this libwkhtmltox I've found in my container to your runtimes repo
  2. then somehow manage to edit Haukcode.WkHtmlToPdfDotNet.targets file in order to copy needed libraries via $(Platform) option
  3. add new class WkHtmlModuleLinuxArm64 with corresponding public const string DLLNAME = "runtimes/linux-arm64/native/libwkhtmltox";
  4. edit factory class and add check for process architecture using System.Runtime.InteropServices.RuntimeInformation.ProcessArchitecture and call new class mentioned before

Did I get everything correct or am I missing something? Is there another way to get this 0.12.5 arm64 libwkhtmltox?

HakanL commented 3 years ago

That looks correct, I haven't done any development on ARM64, but give it a shot, create a fork and see if you can make it run locally first.

HakanL commented 2 years ago

@ilyahryapko Can you see if the latest version fixed this?

ilyahryapko commented 2 years ago

@HakanL Sorry for a late reply. Unfortunately do not have M1 anymore so I am unable to test this

HakanL commented 2 years ago

Version 1.5.81 which is in NuGet now should support Linux ARM64. I have tested it in Docker on a Macbook Air M1, but more testing would be good.