• .NET 5.0项目使用System.Drawing.Common库在Linux系统中报“Gdip”异常


    背景:

      最近我有一个项目中有生成二维码图片的需求,我用Gma.QrCodeNet.Core组件实现,在Window系统上运行一切都是正常的,发布到测试环境CentOS系统后这个接口抛出System.TypeInitializationException:The type initializer for 'Gdip' threw an exception -->System.DllNotFoundException:Unable to load DLL 'libgdiplus' ; The specified module could not be found. 这个错误是在初始化Gdip时出现异常,原因时没有加载到libgdiplus 这个DLL。

    知其所以然:

      出现这个错误是因为Gma.QrCodeNet.Core组件依赖了微软的System.Drawing.Common.dll库,早期的.NET Core版本是没有System.Drawing.Common.dll库的,微软在.NET Core3.0开始提供了这个库,它库封装了GDI+绘图功能。GDI 全名为:Graphics Device Interface(图形设备接口),而GDI是属于Windows系统下的图形设备接口,那么.NET Core有没有实现Linux系统下的“GDI”呢?答案是没有。

      当.NET还没有实现跨平台的时候,mono团队就替微软.NET跨平台操碎了心,mono大量的应用在游戏行业,游戏开发者们既依赖微软的unity3d开发库,又不想使用臃肿低效且闭源的Windows系统。为了让.NET代码运行在Linux系统上,因此诞生了mono项目,大家都知道后来mono被微软招安。而mono团队后来实现了.NET Core在LinuxOS和MacOS系统下的DGI相关接口,他就是libgdiplus。因此System.Drawing.Common.dll库在Windows系统下继续调用原来的GDI实现,在MacOS和LinuxOS下则依赖libgdiplus来实现绘图能力。

      所以,我的项目在Window系统正常运行,在Linxu上则抛出System.TypeInitializationException:The type initializer for 'Gdip' threw an exception -->System.DllNotFoundException:Unable to load DLL 'libgdiplus' ; The specified module could not be found. 异常。要解决这个问题就很简单了,只需要给Linux系统安装libgdiplus库就行了。

    解决问题:

    1.系统简单通过dotnet  XXXXX.dll命令直接运行在linux上,则直接在系统中安装libgdiplus就可以了。

    CentOS安装命令:

    yum install libgdiplus-devel -y
    ln -s /usr/lib64/libgdiplus.so /usr/lib/gdiplus.dll
    ln -s /usr/lib64/libgdiplus.so /usr/lib64/gdiplus.dll

    Ubuntu安装命令

    sudo curl https://raw.githubusercontent.com/stulzq/awesome-dotnetcore-image/master/install/ubuntu.sh|sh

    2.在Docker中运行的项目因为每次重新构建Docker镜像原来的安装就没用了,所以有两个方案,

      第一个方案是基于微软的镜像把libgdiplus加入重新打包一个新的镜像。以后重新部署项目都基于这个新的镜像来构建。

      第二个方案是每次部署项目构建镜像时自动安装libgdiplus库。那么就需要将安装libgdiplus库的命令添加到Dockerfile文件中。Dockerfile文件内容如下:

    FROM mcr.microsoft.com/dotnet/aspnet:5.0
    MAINTAINER pudefu
    
    LABEL description="某某某项目"
    LABEL version="1.0"
    WORKDIR /app
    COPY . .
    
    # 切换apt源为网易
    RUN echo "" > /etc/apt/sources.list  
       && echo "deb http://mirrors.163.com/debian/ stretch main non-free contrib" >> /etc/apt/sources.list  
       && echo "deb http://mirrors.163.com/debian/ stretch-updates main non-free contrib" >> /etc/apt/sources.list  
       && echo "deb http://mirrors.163.com/debian/ stretch-backports main non-free contrib" >> /etc/apt/sources.list  
       && echo "deb-src http://mirrors.163.com/debian/ stretch main non-free contrib" >> /etc/apt/sources.list  
       && echo "deb-src http://mirrors.163.com/debian/ stretch-updates main non-free contrib" >> /etc/apt/sources.list  
       && echo "deb-src http://mirrors.163.com/debian/ stretch-backports main non-free contrib" >> /etc/apt/sources.list  
       && echo "deb http://mirrors.163.com/debian-security/ stretch/updates main non-free contrib" >> /etc/apt/sources.list  
       && echo "deb-src http://mirrors.163.com/debian-security/ stretch/updates main non-free contrib" >> /etc/apt/sources.list
    # 安装gdiplus RUN apt
    -get update -y && apt-get install -y libgdiplus && apt-get clean && ln -s /usr/lib/libgdiplus.so /usr/lib/gdiplus.dll EXPOSE 8888 RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone ENV ASPNETCORE_ENVIRONMENT Development #ENTRYPOINT ["dotnet","XXXXXX.dll"]

    这里安装libgdiplus库只需要增加如下命令即可。

    RUN apt-get update -y && apt-get install -y libgdiplus && apt-get clean && ln -s /usr/lib/libgdiplus.so /usr/lib/gdiplus.dll

    但是libgdiplus库原生提供地址下载太慢,至少正常人都不能忍受。所以我们需要将下载源修改为国内源,比如阿里,腾讯,网易等都可以。最开始我使用的是阿里云的源,但是遇到鉴权相关问题,换了网易的源则没有相关问题,腾讯的没有测试。

    至此,问题解决,又可以愉快的写代码了。

    提示:System.Drawing.Common.dll库

      

  • 相关阅读:
    在Eclipse中运行JAVA代码远程操作HBase的示例
    hbase基本概念和hbase shell常用命令用法
    如何使用putty远程连接linux
    如何在Eclipse下安装SVN插件——subclipse
    solr之创建core(搜索核心,包括索引和数据)的方法
    百度地图api基本用法
    四年大学不如选择培训一年?
    树常见的算法操作
    二叉树常见遍历算法
    Java多线程实现生产者消费者延伸问题
  • 原文地址:https://www.cnblogs.com/pudefu/p/14958587.html
Copyright © 2020-2023  润新知