I have the following problem:
I have a DOCX template with images. Creating the document works. The images are there. Now, when I convert the document to a PDF, it works under Windows, but not under Linux. When my program is running under Linux (Docker container with Alpine image), the images are in the document, but not in the PDF.
In addition, some fonts are missing.
I have already adjusted my Dockerfile (see below).
I’ve included “SkiaSharp.NativeAssets.Linux” in the project.
Unfortunately, without success.
Can you tell me what all needs to be present under Linux to include the images in the PDF?
Dockerfile:
FROM mcr.microsoft.com/dotnet/aspnet:8.0-alpine
RUN apk add --no-cache icu-libs
RUN apk add --no-cache icu-data-full
RUN apk add --no-cache tzdata
ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=false
ENV DOTNET_SystemDrawing_EnableUnixSupport=true
RUN apk update \
&& apk add --no-cache \
icu-libs icu-data-full tzdata fontconfig msttcorefonts-installer \
tiff giflib freetype libpng libjpeg-turbo libx11 \
libgdiplus libc6-compat \
&& update-ms-fonts \
&& fc-cache -f \
&& ln -s /usr/lib/libgdiplus.so /usr/lib/gdiplus.dll
ARG IMAGE_VERSION=unknown
LABEL version=$IMAGE_VERSION
COPY --from=source /src/Services/ReportingService/bin/Release/net8.0/publish /app
ENTRYPOINT ["app/ReportingService"]
@Niebelschuetz
To ensure that images are included in the PDF when converting a DOCX document under a Linux environment, you need to address the underlying causes and implement specific solutions. Here’s a structured approach:
Cause: The absence of necessary libraries and fonts in your Docker container can lead to issues with image rendering and font recognition during the conversion process.
Solution: Follow these steps to ensure all dependencies are correctly installed:
-
Install Required Libraries: Ensure that you have the necessary libraries for handling images and fonts. Add libfontconfig1
to your Dockerfile, as it is required by SkiaSharp, which is used for rendering graphics in Aspose.Words.
-
Use SkiaSharp.NativeAssets: Confirm that you are using the correct version of SkiaSharp.NativeAssets.Linux
. If you encounter dependency issues, consider using SkiaSharp.NativeAssets.Linux.NoDependencies
.
-
Install TrueType Fonts: Since many DOCX documents utilize Windows fonts, install a TrueType font package. You can use msttcorefonts-installer
or copy the font files from a Windows machine to your Linux system. This ensures that the fonts used in your documents are available during conversion.
-
Update Your Dockerfile: Modify your Dockerfile as follows:
FROM mcr.microsoft.com/dotnet/aspnet:8.0-alpine
RUN apk add --no-cache icu-libs icu-data-full tzdata fontconfig msttcorefonts-installer \
&& update-ms-fonts \
&& fc-cache -f \
&& apk add --no-cache libgdiplus libc6-compat
ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=false
ENV DOTNET_SystemDrawing_EnableUnixSupport=true
COPY --from=source /src/Services/ReportingService/bin/Release/net8.0/publish /app
ENTRYPOINT ["app/ReportingService"]
-
Test the Conversion: After implementing these changes, rebuild your Docker image and test the conversion again. Monitor the logs for any errors related to missing images or fonts.
Next Steps: If you continue to experience issues, review the logs for specific error messages and ensure that all required assets are correctly referenced in your DOCX files.
By following these steps, you should be able to resolve the issues with missing images and fonts when converting documents to PDF in a Linux environment. Please let me know if you need further assistance!
@Niebelschuetz Which version of Aspose.Words do you use and which version of SkiaSharp.NativeAssets.Linux
package is include in your project? Could you please attach your input and problematic documents here for testing? We will check the issue and provide you more information.
Thank you for the tip.
I’ve now included the latest Aspose.Words version (25.8.0) and SkiaSharp.NativeAssets.Linux.NoDependencies (3.119.0) instead of SkiaSharp.NativeAssets.Linux.
I’ve also adjusted the Dockerfile as follows:
FROM mcr.microsoft.com/dotnet/aspnet:8.0-alpine
ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=false
RUN apk add --no-cache icu-libs icu-data-full tzdata fontconfig msttcorefonts-installer \
&& update-ms-fonts \
&& fc-cache -f
RUN cd /home && mkdir root && cd root && mkdir .fonts
COPY --from=source /src/Services/ReportingService/Fonts /home/root/.fonts
COPY --from=source /src/Services/ReportingService/bin/Release/net8.0/publish /app
ENTRYPOINT ["app/ReportingService"]
It works now.
I’ve also manually added some fonts to the image because the ttf-mscorefonts-installer package doesn’t install all Microsoft fonts (e.g., Tahoma is missing).
@Niebelschuetz It is perfect that you managed to resolve the problem on your side. Please feel free to ask in case of any further issues. We are always glad to help you.
Hi,
I was noticing a similar issue under Linux in Docker.
We skipped a few Releases but Aspose 25.1 with SkiaSharp.NativeAssets.Linux@2.88.9
was working fine.
With the current Aspose Version 25.8 and SkiaSharp.NativeAssets.Linux@3.119.0
we run into the same issue until we switch to NoDependencies Skia version.
The docker file looks like this
# Unter https://aka.ms/customizecontainer erfahren Sie, wie Sie Ihren Debugcontainer anpassen und wie Visual Studio dieses Dockerfile verwendet, um Ihre Images für ein schnelleres Debuggen zu erstellen.
# Diese Stufe wird verwendet, wenn sie von VS im Schnellmodus ausgeführt wird (Standardeinstellung für Debugkonfiguration).
FROM mcr.microsoft.com/dotnet/runtime:9.0 AS base
WORKDIR /app
# Removed the build preparing stage because I believe it does not matter
# Diese Stufe wird verwendet, um das Dienstprojekt zu veröffentlichen, das in die letzte Phase kopiert werden soll.
FROM build AS publish
ARG BUILD_CONFIGURATION=Release
RUN dotnet publish "./CS.Service.Rendering.DocumentConverter.Word.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false
# Diese Stufe wird in der Produktion oder bei Ausführung von VS im regulären Modus verwendet (Standard, wenn die Debugkonfiguration nicht verwendet wird).
FROM base AS final
ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=0
WORKDIR /app
#Include contrib archive to install windows fonts. Must run before package update
RUN sed -i 's/^Components: main$/& contrib/' /etc/apt/sources.list.d/debian.sources
#Installs "windows fonts"
RUN apt-get update && apt-get install -y ttf-mscorefonts-installer fontconfig
#SkiaSharp dependency of Aspose requires libfontconfig1. See Aspose documentation for this.
RUN apt-get update && apt-get install -y libfontconfig1
#ICU for Culture Information
RUN apt-get update && apt-get install -y libicu-dev
USER $APP_UID
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "CS.Service.Rendering.DocumentConverter.Word.dll"]
I believe we have all dependencies in our dockerfile which are documented here How to Run Aspose.Words in Docker|Aspose.Words for .NET
But doesn’t that mean there is maybe something missing in documentation if the bug persists with the SkiaSharp.NativeAssets.Linux package but is fixed with NoDependency version of skiasharp?
Are there any known disadvantages from switching to no dependency version?
@Serraniel Could you please provide dependencies section from your .csproj
file?
Hi,
the setup is a bit complicated. We have a library which includes Aspose funcationality for Slides, Cells and Words and implements the logics. As it’s used for multiple deployment strategies it’s a bit complex:
Converter.Office.Wrapper.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net48;net9.0</TargetFrameworks>
<OutputType>Library</OutputType>
<GenerateAssemblyInfo>True</GenerateAssemblyInfo>
<ImportWindowsDesktopTargets>true</ImportWindowsDesktopTargets>
<GenerateResourceUsePreserializedResources>true</GenerateResourceUsePreserializedResources>
<LangVersion>10</LangVersion>
<AutoGenerateBindingRedirects>True</AutoGenerateBindingRedirects>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)' == 'net48'">
<UseWindowsForms>true</UseWindowsForms>
</PropertyGroup>
<ItemGroup>
<Reference Include="Gurock.SmartInspect, Version=3.3.9.166, Culture=neutral, PublicKeyToken=a78b0a9303ab7a7c, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>lib\Gurock.SmartInspect.dll</HintPath>
</Reference>
<Reference Include="Gurock.SmartInspect.DebugTrace, Version=3.3.9.166, Culture=neutral, PublicKeyToken=a78b0a9303ab7a7c, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>lib\Gurock.SmartInspect.DebugTrace.dll</HintPath>
</Reference>
<Reference Include="Gurock.SmartInspect.LinqToSql, Version=3.3.9.166, Culture=neutral, PublicKeyToken=a78b0a9303ab7a7c, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>lib\Gurock.SmartInspect.LinqToSql.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Content Include="Gurock.SmartInspect.DebugTrace.dll" />
<Content Include="Gurock.SmartInspect.dll" />
<Content Include="Gurock.SmartInspect.LinqToSql.dll" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Aspose.Cells" Version="25.8.0" />
<PackageReference Include="Aspose.PDF" Version="25.8.0" />
<PackageReference Include="Aspose.Words" Version="25.8.0" />
<PackageReference Include="System.IO" Version="4.3.0" />
<PackageReference Include="System.Resources.Extensions" Version="9.0.8" />
</ItemGroup>
<!-- WINDOWS NORMAL DEPLOYEMENT VIA NUGET -->
<ItemGroup Condition="'$(TargetFramework)' == 'net48'">
<PackageReference Include="Aspose.Slides.NET" Version="25.8.0">
<Aliases>Slides</Aliases>
</PackageReference>
</ItemGroup>
<!-- WINDOWS MICROSERVICES ON PREM VIA NUGET -->
<ItemGroup Condition="'$(TargetFramework)' != 'net48' and '$(OS)' == 'Windows_NT'">
<PackageReference Include="Aspose.Slides.NET" Version="25.8.0">
<Aliases>Slides</Aliases>
</PackageReference>
</ItemGroup>
<!-- LINUX MICROSERVICES VIA LOCAL FILE -->
<ItemGroup Condition="'$(TargetFramework)' != 'net48' and '$(OS)' != 'Windows_NT'">
<Reference Include="NugetPackage">
<HintPath>lib/Aspose.Slides/25.8/net6.0/crossplatform/Aspose.Slides.dll</HintPath>
<Aliases>Slides</Aliases>
</Reference>
<None Update="aspose.slides.drawing.capi_vc14x64.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="aspose.slides.drawing.capi_vc14x86.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="libaspose.slides.drawing.capi_appleclang_arm64.dylib">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="libaspose.slides.drawing.capi_appleclang_x86_64.dylib">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="libaspose.slides.drawing.capi_x86_64_libstdcpp_libc2.23.so">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>
This is used in another library which encapsulates the word tasks we support in our microservices
CS.Rendering.DocumentConverter.Word.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<AssemblyVersion>1.4.0</AssemblyVersion>
<FileVersion>$(AssemblyVersion)</FileVersion>
<Version>$(Assemblyversion)</Version>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.8" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Converter.Office.Wrapper\Converter.Office.Wrapper.csproj" />
<ProjectReference Include="..\CS.Crypto.Utils\CS.Crypto.Utils.csproj" />
<ProjectReference Include="..\CS.RPC.Abstractions\CS.RPC.Abstractions.csproj" />
<ProjectReference Include="..\CS.Utils.Json\CS.Utils.Json.csproj" />
<ProjectReference Include="..\CS.Utils.Workspace\CS.Utils.Workspace.csproj" />
</ItemGroup>
</Project>
And is then used in the specific microservice application for the Linux docker image. The csproj for the word one is the following and is built for Linux docker. The upper library is built throught the Dockerfile for the linux target.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
<Version>$(Assemblyversion)</Version>
<FileVersion>$(Assemblyversion)</FileVersion>
<AssemblyVersion>1.3.4</AssemblyVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration" Version="9.0.8" />
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="9.0.8" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="9.0.8" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="9.0.8" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.8" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="9.0.8" />
<PackageReference Include="Microsoft.Extensions.Logging.Configuration" Version="9.0.8" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="9.0.8" />
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.22.1" />
<PackageReference Include="SkiaSharp.NativeAssets.Linux.NoDependencies" Version="3.119.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\CS.Logging.SmartInspect\CS.Logging.SmartInspect.csproj" />
<ProjectReference Include="..\CS.Logging\CS.Logging.csproj" />
<ProjectReference Include="..\CS.RPC.RabbitMq\CS.RPC.RabbitMq.csproj" />
<ProjectReference Include="..\CS.Services.Rendering.DocumentConverter.Word\CS.Rendering.DocumentConverter.Word.csproj" />
</ItemGroup>
</Project>
This is where we include Skiasharp and the images are missing in the scenario described in my previous message. The Dockerfile from my previous message belongs to this csproj.
Thanks for your help.
@Serraniel Tank you for additional information. Unfortunately, I cannot reproduce the problem on my side. Here is my test Dokerfile:
FROM mcr.microsoft.com/dotnet/runtime:9.0 AS base
WORKDIR /app
FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build
WORKDIR /src
COPY ["TestNet.csproj", "."]
RUN dotnet restore "./TestNet.csproj"
COPY . .
WORKDIR "/src/."
RUN dotnet build "TestNet.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "TestNet.csproj" -c Release -r linux-x64 --no-self-contained -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "TestNet.dll"]
Here are the references added in the test project:
<PackageReference Include="Aspose.Words" Version="25.8.0" />
<PackageReference Include="SkiaSharp.NativeAssets.Linux.NoDependencies" Version="3.119.0" />
Hey,
Sorry for the late response.
<PackageReference Include="SkiaSharp.NativeAssets.Linux.NoDependencies" Version="3.119.0" />
was the version which workes for us, too, but <PackageReference Include="SkiaSharp.NativeAssets.Linux" Version="3.119.0" />
is the broken one.
/ I think i just accidentally deleted the message
@Serraniel I tested with both SkiaSharp.NativeAssets.Linux.NoDependencies
and SkiaSharp.NativeAssets.Linux
and both works fine on my side. Images are rendered properly. In case of SkiaSharp.NativeAssets.Linux
the following line was added to Dokerfile:
RUN apt-get update && apt-get install -y libfontconfig1