在没有 docker 的情况下,Wkhtmltopdf 和 .net 8 的管道损坏了如何解决?

问题描述 投票:0回答:1

我正在使用 wkhtmltopdf 将 cshtml 文件转换为 PDF。在本地运行时,它可以完美运行,没有任何问题(我使用的是 Windows)。但是,当我尝试将应用程序部署到 Docker 容器时,它开始抛出管道损坏的异常。

这是我的dockerfile:

FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base

RUN apt-get update && apt-get install -y --no-install-recommends wget ca-certificates fontconfig libc6 libfreetype6 libjpeg62-turbo libpng16-16 libssl3 libstdc++6 libx11-6 libxcb1 libxext6 libxrender1 xfonts-75dpi xfonts-base zlib1g
RUN wget https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6.1-3/wkhtmltox_0.12.6.1-3.bookworm_amd64.deb
RUN dpkg -i wkhtmltox_0.12.6.1-3.bookworm_amd64.deb

WORKDIR /app
EXPOSE 8080
EXPOSE 8081

FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
ARG BUILD_CONFIGURATION=Release
WORKDIR /src
COPY ["nuget.config", "."]
COPY ["src/Application/Application.csproj", "src/Application/"]
COPY ["src/Application/Rotativa", "src/Application/Rotativa"]
COPY ["src/Services/Services.csproj", "src/Services/"]
RUN dotnet restore "./src/Application/Application.csproj"
COPY . .
WORKDIR "/src/src/Application"
RUN dotnet build "./Application.csproj" -c $BUILD_CONFIGURATION -o /app/build

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

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
RUN chmod -R 755 /app/Rotativa/
ENTRYPOINT ["dotnet", "Application.dll"]

这是我的PDF生成课程

using RazorEngineCore;
using Services.Features.TransferRequest.Models.Interfaces;
using Services.Features.TransferRequest.Repositories;
using Shared.Infrastructure.Interfaces;
using Shared.Infrastructure.ManipulateFiles;
using System.Collections.Concurrent;
using System.Xml.Linq;
using Wkhtmltopdf.NetCore;
using Wkhtmltopdf.NetCore.Options;

namespace Services.Features.TransferRequest.UseCases.Services;

public class PdfGeneratorService(IRazorEngine razorEngine, IGeneratePdf generatePdf, ILoggerActionEnrichService logger, IFilesReader filesReader) : IPdfGeneratorService
{
    private readonly string _namespace = $"{typeof(TransferRequestModule).Namespace}.Models.Templates";
    public async Task<MemoryStream> GeneratePdfAsync<TModel>(TModel model, string fileName)
    {
        try
        {
            var template = await filesReader.ReadFileWithMemoryFirstAsync(_namespace, fileName, TypeArchives.CSHTML); ;
            var html = await GenerateHtmlAsync<TModel>(model, template);

            return await GeneratePdf(html);
        }
        catch (Exception ex)
        {
            logger.Add($"Problemas para gerar o pdf \n Message: {ex.Message}");
            logger.Add($"StackTrace: {ex.StackTrace}");
            logger.Add($"InnerException: {ex.InnerException}");
            logger.Add($"Exception: {ex}");
            throw;
        }
    }

    private async Task<MemoryStream> GeneratePdf(string html)
    {
        generatePdf.SetConvertOptions(new ConvertOptions
        {
            PageMargins = new Margins(0, 0, 0, 0),
        });

        var pdf = await Task.Run(() => generatePdf.GetPDF(html));
        var pdfStream = new MemoryStream();
        await pdfStream.WriteAsync(pdf, 0, pdf.Length);
        pdfStream.Position = 0;
        return pdfStream;
    }

    private async Task<string> GenerateHtmlAsync<TModel>(TModel model, string template)
        => await (await razorEngine.CompileAsync<RazorEngineTemplateBase<TModel>>(template))
            .RunAsync(instance =>
            {
                instance.Model = model;
            });
}

问题发生在以下行:

var pdf = await Task.Run(() => generatePdf.GetPDF(html));

这是堆栈跟踪:

StackTrace:    at System.IO.Pipes.PipeStream.CheckWriteOperations()
   at System.IO.StreamWriter.Flush(Boolean flushStream, Boolean flushEncoder)
   at System.IO.StreamWriter.Dispose(Boolean disposing)
   at System.IO.TextWriter.Dispose()
   at Wkhtmltopdf.NetCore.WkhtmlDriver.Convert(String wkhtmlPath, String switches, String html)
   at Wkhtmltopdf.NetCore.GeneratePdf.GetPDF(String html)
   at Services.Features.TransferRequest.UseCases.Services.PdfGeneratorService.<>c__DisplayClass7_0.<GeneratePdf>b__0() in /src/src/Services/Features/TransferRequest/UseCases/Services/PdfGeneratorService.cs:line 42
   at System.Threading.Tasks.Task`1.InnerInvoke()
   at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location ---
   at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread)
--- End of stack trace from previous location ---
   at Services.Features.TransferRequest.UseCases.Services.PdfGeneratorService.GeneratePdf(String html) in /src/src/Services/Features/TransferRequest/UseCases/Services/PdfGeneratorService.cs:line 42
   at Services.Features.TransferRequest.UseCases.Services.PdfGeneratorService.GeneratePdfAsync[TModel](TModel model, String fileName) in /src/src/Services/Features/TransferRequest/UseCases/Services/PdfGeneratorService.cs:line 23

有人有解决办法吗?

.net linux docker wkhtmltopdf
1个回答
0
投票

您可以通过以下链接参考问题原因及解决方案:“https://stackoverflow.com/a/79163054/28591255”。我还将提供一些额外的见解以进一步增强该解决方案。 我会改变: “运行 chmod -R 755 /app/Rotativa/”“RUN mkdir -p /app/Rotativa/Linux &&
mv /usr/local/bin/wkhtmltopdf /app/Rotativa/Linux/ &&
chmod 755 /app/Rotativa/Linux/wkhtmltopdf"

祝你好运!

© www.soinside.com 2019 - 2024. All rights reserved.