.net core 在Liunx 使用System.Drawing.Common 出现Gdip问题

问题:

当我们使用画图之类的功能可能会引用System.Drawing.Common,或者间接引用它,由于它是依赖Windows系统,所以我们在Windows是正常的,放在Linux就会出现类似于下面这种错误

System.TypeInitializationException: The type initializer for 'Gdip' threw an exception.
---> System.DllNotFoundException: Unable to load shared library 'libgdiplus' or one of its dependencies. In order to help diagnose loading problems, consider setting the LD_DEBUG environment variable: liblibgdiplus: cannot open shared object file: No such file or directory

 

解决方案:

因此我们需要在Linux服务器上安装libgdiplus(如果直接发布到服务器,则装在服务器上,如果通过docker发布则装在docker容器里面),通过libgdiplus进行图像处理。

方案一:在dockerfile添加集成libgdiplus的代码

当我们使用docker时,可以在dockerfile中build之前加入这一行代码,每次生成镜像就会下载安装libgdiplus

RUN apt-get update \
    && apt-get install -y libc6-dev libgdiplus \
    && if [ ! -e /usr/lib/libgdiplus.so ]; then ln -s libgdiplus.so /usr/lib/libgdiplus.so; fi

网上很多人这一步就可以了,可能是因为System.Drawing.Common引用的版本<= 5.0.3。如果大于这个版本还是会报错,需要在工程文件手动配置

  <ItemGroup>
	  <RuntimeHostConfigurationOption Include="System.Drawing.EnableUnixSupport" Value="true" />
  </ItemGroup>

可能是新版本默认不支持linux,需要在这里配置启用,之前的版本默认支持,所以不需要配置。这里就解决了

方案二:自己制作基础镜像,集成libgdiplus

由于每次在生成镜像的时候都需要安装libgdiplus,导致发布会很花时间,可以自己将dotnet运行时和libgdiplus 打包成一个镜像 ,放在dockerhub 或者阿里云上面 ,dockerfile 中基础镜像就可以用我们自己的镜像了

1. 下载运行时源镜像,这里以.net 6.0为例

docker pull mcr.microsoft.com/dotnet/aspnet:6.0

2. 进入容器并安装libgdiplus

docker run -it mcr.microsoft.com/dotnet/aspnet:6.0 /bin/bash
apt-get update -y
apt-get install -y libgdiplus
apt-get clean
ln -s /usr/lib/libgdiplus.so /usr/lib/gdiplus.dll  # 某些.NET应用可能需要这个符号链接

3. 退出容器并创建新镜像

docker commit <容器id> <新镜像名>:<tag版本号>

4. 推送到阿里云(前提是需要在 阿里云镜像服务 中添加仓库,这里也可以直接登录docker hub,推送到docker hub上面)

$ docker login --username=13038*****@qq.com(账号) registry.cn-hangzhou.aliyuncs.com
$ docker tag [新镜像id] registry.cn-hangzhou.aliyuncs.com/xxx(仓库名称)/dotnet-libgdiplus:[镜像版本号]
$ docker push registry.cn-hangzhou.aliyuncs.com/xxx(仓库名称)/dotnet-libgdiplus:[镜像版本号]

 上传后可以在后台看到基础镜像

然后我们的dockerfile 基础镜像直接用阿里云我们打包的基础镜像就行了(前提是我们打包的镜像必须在阿里云设置为公开,否则在我们拉取镜像之前要先登录才能拉取)

方案三:使用SkiaSharp 和 imagesharp 

针对于linux平台,官方已经提供了替代库 SkiaSharp imagesharp ,不用System.Drawing.Common。

两个替代库的区别?

 

 

很多包也支持了这两个替代库,比如说生成二维码的 包 ZXing.Net,如果使用这个包需要和上面一样安装libgdiplus ,因为这个包依赖于System.Drawing.Common。但是这个包提供了不依赖System.Drawing.Common,依赖SkiaSharp 和 imagesharp 进行图像处理

 

比如我们 选择 ZXing.Net.Bindings.SkiaSharp后,还需要安装 SkiaSharp.NativeAssets.Linux.NoDependencie ,否则还是会出现错误,这里是一个坑。

 

posted @ 2025-01-09 16:59  Joni是只狗  阅读(640)  评论(0)    收藏  举报