在 azure 中发布为应用服务后,使用 DinkToPDF 进行 PDF 转换时无法加载外部库“libwkhtmltox.dll”

Posted

技术标签:

【中文标题】在 azure 中发布为应用服务后,使用 DinkToPDF 进行 PDF 转换时无法加载外部库“libwkhtmltox.dll”【英文标题】:Unable to load External library "libwkhtmltox.dll" while using DinkToPDF for PDF conversion after publishing as app service in azure 【发布时间】:2019-10-24 22:01:14 【问题描述】:

我正在使用 DinkToPDF 库将 html 字符串转换为等效的 PDF。 要使用这个库,我们必须导入提供的本地库 libwkhtmltox.dll。当我在本地运行我的 .net 核心项目时,这工作正常,但是当我尝试在 Azure 中将我的 Web 项目作为应用服务发布时,我收到以下错误,

未处理的异常:System.DllNotFoundException:无法加载共享库“/home/site/wwwroot/libwkhtmltox.dll”或其依赖项之一。为了帮助诊断加载问题,考虑设置 LD_DEBUG 环境变量:/home/site/wwwroot/libwkhtmltox.dll: cannot open shared object file: No such file or directory

我在下面的 startup.cs 文件中引用了库的使用情况。

    internal class CustomAssemblyLoadContext : AssemblyLoadContext
    
        public IntPtr LoadUnmanagedLibrary(string absolutePath)
        
            return LoadUnmanagedDll(absolutePath);
        
        protected override IntPtr LoadUnmanagedDll(String unmanagedDllName)
        
            return LoadUnmanagedDllFromPath(unmanagedDllName);
        

        protected override Assembly Load(AssemblyName assemblyName)
        
            throw new NotImplementedException();
        
    
        public void ConfigureServices(IServiceCollection services)
        
            services.AddSingleton(typeof(IConverter), new SynchronizedConverter(new PdfTools()));
            var context = new CustomAssemblyLoadContext();
            context.LoadUnmanagedLibrary(Path.Combine(Directory.GetCurrentDirectory(), "libwkhtmltox.dll"));
         .
         .
         .
        

请帮我找出这个错误的解决方案。

【问题讨论】:

你如何解决这个问题?可以更新吗? 【参考方案1】:

你需要设置库的绝对路径,对于windows不需要使用“.dll”,在我的例子中它被放置在[project_root]/wkhtmltox/v0.12.4/[x_64|x_86]

var architectureFolder = (IntPtr.Size == 8) ? "x_64" : "x_86";
var wkHtmlToPdfFileName = "libwkhtmltox";
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))

    wkHtmlToPdfFileName += ".so";

else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))

    wkHtmlToPdfFileName += ".dylib";


var wkHtmlToPdfPath = Path.Combine(
    new string[] 
        _hostingEnvironment.ContentRootPath,
        "wkhtmltox",
        "v0.12.4",
        architectureFolder,
        wkHtmlToPdfFileName
    );

CustomAssemblyLoadContext context = new CustomAssemblyLoadContext();
context.LoadUnmanagedLibrary(wkHtmlToPdfPath);
services.AddSingleton(typeof(IConverter), new SynchronizedConverter(new PdfTools()));

【讨论】:

【参考方案2】:

您必须将 dll 扩展名复制到项目的根目录

之后你必须创建一个内部类来加载 dll

将此添加到您的课程中

using System.Runtime.Loader;
using System.Reflection;

要包括的方法:

    internal class CustomAssemblyLoadContext : AssemblyLoadContext
    
        public IntPtr LoadUnmanagedLibrary(string absolutePath)
        
            return LoadUnmanagedDll(absolutePath);
        
        protected override IntPtr LoadUnmanagedDll(string unmanagedDllName)
        
            return LoadUnmanagedDllFromPath(unmanagedDllName);
        

        protected override Assembly Load(AssemblyName assemblyName)
        
            throw new NotImplementedException();
        
    

【讨论】:

【参考方案3】:

在 dockerfile 中将以下命令插入到组件引擎 html 到 pdf 中:

FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base

RUN apt-get update

RUN apt-get install -y apt-utils

RUN apt-get install -y libgdiplus

RUN apt-get install -y libc6-dev
 
RUN ln -s /usr/lib/libgdiplus.so/usr/lib/gdiplus.dll

【讨论】:

【参考方案4】:

试试这个: 从https://github.com/rdvojmoc/DinkToPdf/tree/master/v0.12.4下载包

通过自定义程序集引用将其添加到您的项目引用并在您的启动项目中注册。 这是自定义程序集加载上下文,可以从绝对路径加载库。

internal class CustomAssemblyLoadContext : AssemblyLoadContext

    public IntPtr LoadUnmanagedLibrary(string absolutePath)
    
        return LoadUnmanagedDll(absolutePath);
    
    protected override IntPtr LoadUnmanagedDll(String unmanagedDllName)
    
        return LoadUnmanagedDllFromPath(unmanagedDllName);
    

    protected override Assembly Load(AssemblyName assemblyName)
    
        throw new NotImplementedException();
    

在 Statup.cs 添加以下代码。 在创建转换器之前调用 CustomAssemblyLoadContext:

CustomAssemblyLoadContext 上下文 = new CustomAssemblyLoadContext(); context.LoadUnmanagedLibrary(path);

var 转换器 = new SynchronizedConverter(new PdfTools()); services.AddSingleton(转换器); services.AddSingleton(typeof(IConverter), new SynchronizedConverter(new PdfTools()));

【讨论】:

以上是关于在 azure 中发布为应用服务后,使用 DinkToPDF 进行 PDF 转换时无法加载外部库“libwkhtmltox.dll”的主要内容,如果未能解决你的问题,请参考以下文章

横向扩展后 Azure 应用服务实例可用多长时间?

带有 .NET 后端的 Azure 移动服务 - 数据库中已经存在一个对象

azure 移动服务活动目录身份验证 X-ZUMO-AUTH 令牌在注销后在邮递员中有效

使用 CORS 的应用程序在 Azure 中不起作用

Azure 应用服务中的 LDAP 身份验证失败

WEBSITE_RUN_FROM_PACKAGE 参数设置为 1 后,如何在 Azure 门户上编辑 Azure 功能代码?