Aspose.PDF Running .NET 6 project in Docker throws Globalization.CultureNotFoundException after deployment on linux

@Sukhvinder
What version of the library are you using?
If Aspose.Pdf, then try Aspose.Pdf.Drawing instead.

@sergei.shibanov Currently we are using Aspose.PDF 23 as per attached sectionasposeversion.PNG (30.9 KB)

Can you please let us know which version we can use as We need to purchase license ,Which product we can buy license Aspose.PDF or Aspose.PDF.Drawing ?Please confirm.

@Sukhvinder
Both libraries work with the same license. When buying, it is better to clarify (specify) it. But technically now so. Aspose.Pdf.Drawing is better for working in Linux systems.

@sergei.shibanov Thanks you, As per your suggestion now culture not found error resolved but now it is failing when we are saving the document and throwing below error
Throwing error on this line - pdfDocument.Save(streamsd, Aspose.Pdf.SaveFormat.Pptx);

Do you have any idea how can we save ppt and return as byte when i am skipping above line then it is returning empty.
Stack Trace

RenderPptxTemplateAsync Document exception: System.IO.IOException: Read-only file system : ‘/tmp/TempFonts’
at System.IO.FileSystem.CreateDirectory(String fullPath)
at #=z74Fq7n$Gl64wbpnfW9MesDaMR9voN28ahQ==.#=zauMb4Wt5DjmD()
at #=z74Fq7n$Gl64wbpnfW9MesDaMR9voN28ahQ==…ctor()
at #=zxcMJNWhEaXXFJp7zsNrx15gu0CFU.#=zfy1V6mc=(String #=zO$fm2lM=, #=zmYkWHgSPEk2G2YygMTYBqkFypBYV #=zg$b4LR4=)
at #=zbS5D3o0o95iypdB$Sd_RNv73aPM2cad4gw==.#=zL0G6SvejW79X(#=zmYkWHgSPEk2G2YygMTYBqkFypBYV #=zg$b4LR4=)
at #=zbS5D3o0o95iypdB$Sd_RNv73aPM2cad4gw==.#=zT$GNo1WPuBg1y7CvSg==(#=zmYkWHgSPEk2G2YygMTYBqkFypBYV #=zg$b4LR4=)
at #=zRGUKcHGury$zDrZudw0JoCKJGSc3dqDGtdpTNV4=.#=ziAVWnZJq9dJyFfNtdJioreLNbINK(#=za0VtmMCe35HuTO$qKIMglsst$1PyshXlQg== #=zbT5$1akeHUx1, #=za0VtmMCe35HuTO$qKIMglsst$1PyshXlQg== #=zi_oVOYlNRmHg)
at #=zRGUKcHGury$zDrZudw0JoCKJGSc3dqDGtdpTNV4=.#=z9X8Ojh6OWax1(#=zrgCSNDnanlcpyvy2fYquewv3apzU #=zvd0uFOc=, Boolean #=zIjiqPnLA16SOSueI0Q==, Boolean #=z8Fuf$yo=)
at #=zRGUKcHGury$zDrZudw0JoCKJGSc3dqDGtdpTNV4=.#=zU2xcXhc=(#=zrgCSNDnanlcpyvy2fYquewv3apzU #=zvd0uFOc=, Boolean #=zIjiqPnLA16SOSueI0Q==)
at #=ztfC1n7uu8ojclO2l0Z9dwIb2vP9AbxA6lw==…ctor(#=zscRVqV1NAej$IF4yFwAStwmnTjrb #=zcqg9ZFM=, #=zK$fBLfaTUno2VAB6Enl7Ck24XJHmXpY$OpZxCSY= #=z9BlIXgs=, List1 #=zXpTsEDg=, List1 #=z04dzXjo=, Boolean #=zUz6EL88j_6yAXKVvWK2m60$uEUB4o27EXg==, Boolean #=ziKukhXusCfdCVN2EWw==)
at #=zKp42sDdBCeeEYwrDGY1KZ_wsvR$8s7NKxw==.#=zzqBFrS_KCTkUf2$fAA==(#=zw1PiL7Ahw0xEELEsb_2JzaU= #=z3McrTS8=, Single #=zK5IEPKvdSpRZ, Single #=zVGlfhIKQ2Dom, #=zK$fBLfaTUno2VAB6Enl7Ck24XJHmXpY$OpZxCSY= #=z9BlIXgs=, Boolean #=zUz6EL88j_6yAXKVvWK2m60$uEUB4o27EXg==, Boolean #=ziKukhXusCfdCVN2EWw==, #=zKp42sDdBCeeEYwrDGY1KZ_wsvR$8s7NKxw== #=ze6VFiEc=)
at #=zKp42sDdBCeeEYwrDGY1KZ_wsvR$8s7NKxw==.#=zzqBFrS_KCTkUf2$fAA==(#=zw1PiL7Ahw0xEELEsb_2JzaU= #=z3McrTS8=, Single #=zK5IEPKvdSpRZ, Single #=zVGlfhIKQ2Dom, #=zKp42sDdBCeeEYwrDGY1KZ_wsvR$8s7NKxw== #=ze6VFiEc=)
at #=zKp42sDdBCeeEYwrDGY1KZ_wsvR$8s7NKxw==.#=z_M185yN6winK6Wa1Bx$Pjss=(#=zw1PiL7Ahw0xEELEsb_2JzaU= #=z3McrTS8=, SizeF #=zEW0qqSo=)
at #=z4c2bNQ96jlP0zE9dMfUiwnUn4fMi$q5N0mYitbY=.#=zINuimrg=(IList1 #=zd04maSBOsEoG, #=zisxCjYoVfthZiHZKKmyWE9KSU2J3jzrsiA== #=zqCRAJ2c=, #=zt$$TpbTPIW2LOxlYHFfW$VkLPL7U7RDjwnA$mcs= #=zC8H9DY8=) at #=zM6R78iELVOUwC6I6Z605bGSV4f6w.#=z0v4AuMbh2MPwA3X_Ag==(List1 #=zbV1UD50=)
at #=zgWwdw$lh_npc4NQkVOD7C6l_wciiE1FMBA==.#=z2chjyOQrOBHt(List`1 #=zd04maSBOsEoG, Stream #=zhGZCK3QA$7Vf, PptxSaveOptions #=zC8H9DY8=)
at #=zgWwdw$lh_npc4NQkVOD7C6l_wciiE1FMBA==.#=zINuimrg=(Document #=zHVmFA6o=, Stream #=zhGZCK3QA$7Vf, PptxSaveOptions #=zC8H9DY8=)
at Aspose.Pdf.Document.#=zEoWK9eIwWhSp(Stream #=z8WYr_7pbgzEv, SaveOptions #=zC8H9DY8=)
at Aspose.Pdf.Document.#=zEoWK9eIwWhSp(Stream #=z8WYr_7pbgzEv, SaveFormat #=zjMZpFjo=)
at Aspose.Pdf.Document.Save(Stream outputStream, SaveFormat format)
at CI.DataAggregation.Services.PdfExport.PdfTemplateLoader.RenderPptxTemplateAsync(String template) in /src/services/CI.DataAggregation/Services/PdfExport/PdfTemplateLoader.cs:line 159

@Sukhvinder
As I understand from Stack Trace, you need the ability to access ‘/tmp/TempFonts’ (I suppose some temporary files are created there). It is necessary to open the possibility of writing to this folder for the library.

@sergei.shibanov Yes , When trying to save it is accessing /tmp/TempFonts path to save and get document object So How can i resolve this? Do we need to add permission in code?OR Do we need to add lines of code in docker file ?Please suggest!

@Sukhvinder
You, in your environment, need to share the folder and give the appropriate rights to the library. So that the library can write and read there. This already applies to the deployment, not the library, and I can’t advise something more specific.

@sergei.shibanov Thanks you for you support, I am able to export PPT. Here I need help for one of the task - The system shall set the ‘VBASigned’ property to ‘False’ to disable macros in the aspose PPT using aspose pdf library, I did not find code references for disable the macros with aspose PDF drawing packages, Can you please help me to give property to disable macros in code while exporting ppt?

@Sukhvinder
Please clarify:
Are you exporting a pdf document to a ppt document and need to disable macros in the resulting ppt document?
Or
Are you reading a ppt document for converting it to pdf?
And you need to not use micros in readed ppt document while convert it to pdf?

@Sukhvinder
Since this is another question (not the one listed in the thread title) a new thread should be created for it. To make it easier for other users to find the discussions they are interested in.

It seems
<PredefinedCulturesOnly>false</PredefinedCulturesOnly>
is enough

@braalias
Perhaps so, I don’t remember if I have already checked this option.
Thanks for the comment, I’ll keep that in mind.

@Sukhvinder
@braalias
The development team responded:

When using the library on operating systems other than Windows (such as macOS or Linux), additional system libraries required for proper operation must be installed, for example libgdiplus. In addition, the standard mcr.microsoft.com/dotnet/runtime:8.0 image does not include any fonts, so fonts must be installed explicitly as well.

Below is a universal Dockerfile that addresses localization issues when running in Azure Kubernetes Service (AKS) and installs all required system libraries and fonts needed for the application to function correctly. A sample conversion program is also provided, demonstrating how to configure an external fonts directory.

# -------------------------------------------------------------------------------------------------
# Dockerfile (multi-stage) for .NET 8
#
# Goal:
# - Keep the final image small (runtime-only)
# - Still have fonts + libgdiplus + ICU + locales available at runtime
# - Avoid Visual Studio "fast mode" surprises by installing runtime dependencies in the `base` stage,
#   because VS debug containers are often built from `base`.
# -------------------------------------------------------------------------------------------------
7
# =========================
# Stage 1: base (runtime)
# =========================
# This is the runtime image used for:
# - Visual Studio "fast mode" (Debug) in many setups
# - The final production container (we "FROM base" later)
#
# We install ALL runtime OS dependencies here so they are always present
# regardless of how VS builds/runs the container.
FROM mcr.microsoft.com/dotnet/runtime:8.0 AS base

USER root
WORKDIR /app

# Install:
# - libgdiplus            : required for System.Drawing / GDI+ compatibility
# - fontconfig + fonts-*  : system fonts and font discovery via fc-list/fc-cache
# - locales               : to enable UTF-8 locales (useful for globalization + text)
# - ca-certificates       : TLS roots (often needed for HTTPS downloads/calls)
#
# Notes:
# - We generate en_US.UTF-8 locale and refresh font cache.
# - We keep the layer clean by removing apt lists after install.
RUN set -eux; \
    apt-get update; \
    apt-get install -y --no-install-recommends \
        libgdiplus \
        fontconfig \
        fonts-dejavu-core \
        fonts-dejavu-extra \
        fonts-liberation \
        locales \
        ca-certificates \
    ; \
    sed -i 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen; \
    locale-gen; \
    fc-cache -f -v; \
    rm -rf /var/lib/apt/lists/*

# Enable .NET globalization (ICU is included in the Debian-based dotnet images).
ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=false
ENV LC_ALL=en_US.UTF-8
ENV LANG=en_US.UTF-8

# =========================
# Stage 2: build (SDK)
# =========================
# This stage contains the full .NET SDK and is used only to compile the project.
# It will NOT be shipped to production.
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build

ARG BUILD_CONFIGURATION=Release
WORKDIR /src

# Copy only the project file first to leverage Docker layer caching for restore.
COPY ["DockerApp.csproj", "./"]
RUN dotnet restore "./DockerApp.csproj"

# Copy the rest of the source code and build.
COPY . .
RUN dotnet build "./DockerApp.csproj" -c $BUILD_CONFIGURATION -o /app/build

# =========================
# Stage 3: publish
# =========================
# This stage produces the published output (self-contained app files layout),
# which is what we will copy into the final runtime image.
FROM build AS publish

ARG BUILD_CONFIGURATION=Release
RUN dotnet publish "./DockerApp.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false

# =========================
# Stage 4: final (production runtime)
# =========================
# The final image is based on `base`, so it contains:
# - fonts
# - fontconfig cache
# - libgdiplus
# - UTF-8 locale setup
#
# Then we copy only the published application output.
FROM base AS final

WORKDIR /app
COPY --from=publish /app/publish .

ENTRYPOINT ["dotnet", "DockerApp.dll"]
using Aspose.Html;
using Aspose.Html.Converters;
using Aspose.Html.Saving;
using Aspose.Html.Services;
using System.Reflection;
using System.Text;

namespace DockerApp
{
    internal class Program
    {
        static void Main(string[] args)
        {
            var src = File.ReadAllText("ReportsSummarypptx.html");
            var cfg = new Configuration();
            var options = new PdfSaveOptions();

            // This is the default value; you can remove these
            // lines or replace the fonts directory with a different path. 
            var uas = cfg.GetService<IUserAgentService>();
            uas.FontsSettings.SetFontsLookupFolder("/usr/share/fonts", true);

            using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(src)))
            using (var doc = new HTMLDocument(stream, ".", cfg))
            {
                Converter.ConvertHTML(doc, options, "output.pdf");
            }
        }
    }
}