.net 在Linux/Docker报错The type initializer for ‘Gdip’ threw an exception 图片操作报错System.Drawing.Common

一、先说结论(解决方法)

.Net 6.0适用:

第1步:以下是我添加到每个 *.csproj 文件中的内容:

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

第2步:以下是我的 Dockerfile 中的内容:

FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base
#FROM mcr.microsoft.com/dotnet/sdk:6.0 AS base
#FROM mcr.microsoft.com/dotnet/runtime:6.0 AS base
WORKDIR /app
# 设置导出端口
EXPOSE 9026

RUN apt-get update && \
    apt-get install -y --allow-unauthenticated libgdiplus libc6-dev

COPY . /app

ENTRYPOINT ["dotnet", "XXXXXXXXXXXXXXXX.dll"]

 

 FROM mcr.microsoft.com/dotnet/aspnet:6.0 as base
  RUN apt-get update && apt-get install -y libgdiplus
  WORKDIR /app
  EXPOSE 80

无效方法:

1、通过将 runtimeconfig.json 文件中的 System.Drawing.EnableUnixSupport运行时配置开关设置为 true 来启用对 .NET 6 中非 Windows 平台的支持。在启动项目根目录创建 runtimeconfig.template.json 文件,复制上面的内容

{
 "runtimeOptions": {
    "configProperties": {
       "System.Drawing.EnableUnixSupport": true
    }
 }
}

2、 通过代码设置:

AppContext.SetSwitch("System.Drawing.Common.EnableUnixSupport", true);

3、在 appsettings.json 文件中,添加以下配置来启用该功能:

{
  "System.Drawing.Common": {
    "SupportedOperatingSystems": "Windows, Linux, OSX"
  }
}

二、再讲道理:

在 .NET Core 中可以通过安装 System.Drawing.Common 来使用 Image、Bitmap 等类型。

.NET Core 本身不包括和图片有关的 Image、Bitmap 等类型。对于图片的操作在我们开发中很常见,比如:生成验证码、二维码等等。在 .NET Core 的早期版本中,有 .NET 社区开发者实现了一些 System.Drawing 的 Image等类型实现的组件,比如 CoreCompat.System.DrawingZKWeb.System.Drawing等。后来微软官方提供了一个组件 System.Drawing.Common实现了 System.Drawing 的常用类型,以 Nuget 包的方式发布的。今天就围绕它来讲一讲这里面的坑。

System.Drawing.Common 组件提供对GDI+图形功能的访问。它是依赖于GDI+的,那么在Linux上它如何使用GDI+,因为Linux上是没有GDI+的。Mono 团队使用C语言实现了GDI+接口,提供对非Windows系统的GDI+接口访问能力(个人认为是模拟GDI+,与系统图像接口对接),这个就是 libgdiplus。进而可以推测 System.Drawing.Common 这个组件实现时,对于非Windows系统肯定依赖了 ligdiplus 这个组件。如果我们当前系统不存在这个组件,那么自然会报错,找不到它,安装它即可解决。

libgdiplus github: https://github.com/mono/libgdiplus

旧行为

在 .NET 6 之前,使用 System.Drawing.Common 包不会产生任何编译时警告,也不会引发运行时异常。

新行为

从 .NET 6 开始,平台分析器会在为非 Windows 操作系统编译引用代码时发出编译时警告。此外,除非您设置配置选项,否则会引发以下运行时异常:

错误: The type initializer for 'Gdip' threw an exception.

通过对 NuGet 包的分析,我们观察到它System.Drawing.Common主要用于跨平台的图像处理,例如 QR 码生成器和文本渲染。我们没有注意到大量的图形使用,因为我们的跨平台图形支持不完整。SkiaSharp 和 ImageSharp 通常很好地支持我们System.Drawing.Common在非 Windows 环境中看到的用法。

System.Drawing.Common将仅在 Windows 窗体和 GDI+ 的上下文中继续发展。

要将这些 API 用于跨平台应用程序,请迁移到以下库之一:

或者,您可以通过在runtimeconfig.json文件中将System.Drawing.EnableUnixSupport 运行时配置开关设置为来启用对 .NET 6 中的非 Windows 平台的支持:true

 

添加此配置开关是为了让严重依赖此包时间的跨平台应用程序迁移到更现代的库。但是,不会修复非 Windows 错误。此外,此开关已在 .NET 7 中删除。

命令失效问题

有些同学可能遇到使用了命令无效的问题,据我猜测可能是包源或者是你本身环境导致安装失败,目前给出的解决办法有两个,一个是clone github源码编译安装,一个是下载离线包安装:https://pkgs.org/download/libgdiplus

参考:

https://stackoverflow.com/questions/67091719/system-drawing-common-the-type-initializer-for-gdip-threw-an-exception

 .NET Core 图片操作在 Linux/Docker 下的坑 - 从未被超越 - 博客园

linux docker 中使用 System.Drawing.Common 异常 System.Drawing.Common 仅在 Windows 上受支持_让docker 支持system.drawing-CSDN博客

.net 6 部署在Docker环境,报错The type initializer for ‘Gdip’ threw an exception – Vlins

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值