在要求输入邮箱的文本域,请填写真实的邮件地址。非真实邮件地址,将收不到回复信息。

.net core在Linux系统报Gdip异常的问题

.net core 清风 824℃ 0评论

背景

.net core 应用中使用了Excel文件导出,发现Excel导出失败,导出的操作出现了异常。看了一下是Gdip的这个异常。这个异曾经见到过,记得也很快解决了,不晓得为什么又会出现呢?仔细看了一下,详细错误还是有点差别。经过确认上一次安装的libc6-devlibgdiplus是存在的,并没有丢失或者损坏。

根据异常信息,基本可以确定是引用System.Drawing.Common类库引起的问题,经过排查发现引用的Excel组件Magicodes.IE.Excel.Abp包中有使用System.Drawing.Common。前几天还好好的,现在为何System.Drawing.Common不支持非Windows平台呢?只是确定引用的System.Drawing.Common库的版本是6.0,其他的就没有太多线索。

最后又看一遍异常信息,根据异常提示打开所提示的网址看一下:

https://aka.ms/systemdrawingnonwindows

提示中断性变更,仅在Windows上支持 System.Drawing.Common

System.Drawing.Common NuGet 包现在被归为 Windows 特定的库。 在为非 Windows 操作系统编译时,平台分析器会在编译时发出警告。

在非 Windows 操作系统上,除非设置了运行时配置开关,否则将引发 TypeInitializationException 异常,其中 PlatformNotSupportedException 作为内部异常。

旧行为

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

新行为

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

.net core在Linux系统报Gdip异常的问题-第0张图片

The type initializer for ‘Gdip’ threw an exception.
System.TypeInitializationException: The type initializer for ‘Gdip’ threw an exception.
—> System.PlatformNotSupportedException: System.Drawing.Common is not supported on non-Windows platforms. See https://aka.ms/systemdrawingnonwindows for more information.
at System.Drawing.LibraryResolver.EnsureRegistered()
at System.Drawing.SafeNativeMethods.Gdip.PlatformInitialize()
at System.Drawing.SafeNativeMethods.Gdip..cctor()
— End of inner exception stack trace —
at System.Drawing.SafeNativeMethods.Gdip.GdipGetGenericFontFamilySansSerif(IntPtr& fontfamily)
at System.Drawing.FontFamily.GetGdipGenericSansSerif()
at System.Drawing.FontFamily.get_GenericSansSerif()
at System.Drawing.Font.CreateFont(String familyName, Single emSize, FontStyle style, GraphicsUnit unit, Byte charSet, Boolean isVertical)
at System.Drawing.Font..ctor(String familyName, Single emSize, FontStyle style, GraphicsUnit unit, Byte gdiCharSet, Boolean gdiVerticalFont)
at OfficeOpenXml.ExcelRangeBase.AutoFitColumns(Double MinimumWidth, Double MaximumWidth)
at OfficeOpenXml.ExcelRangeBase.AutoFitColumns(Double MinimumWidth)
at OfficeOpenXml.ExcelRangeBase.AutoFitColumns()
at OfficeOpenXml.ExcelColumn.AutoFit()
at Magicodes.ExporterAndImporter.Excel.Utility.ExportHelper1.AddStyle() at Magicodes.ExporterAndImporter.Excel.Utility.ExportHelper1.AddHeaderAndStyles()
at Magicodes.ExporterAndImporter.Excel.ExcelExporter.ExportHeaderAsByteArray(String[] items, String sheetName)

引入的版本

此更改会影响源兼容性和二进制兼容性。

更改原因

由于 System.Drawing.Common 被设计为 Windows 技术的精简包装器,因此其跨平台实现欠佳。

libgdiplus 是本机端 System.Drawing.Common 跨平台实现的主要提供程序。 libgdiplus 实际上是对 System.Drawing.Common 所依赖的 Windows 部分的重新实现。 该实现使 libgdiplus 成为一个重要的组件。 它大约有 30,000C 代码,大部分未经测试,而且缺少很多功能。 libgdiplus 还具有许多用于图像处理和文本呈现的外部依赖项,例如 cairopango 和其他本机库。 这些依赖项使得维护和交付组件更具挑战性。 自从包含 Mono 跨平台实现以来,我们已将许多从未得到修复的问题重定向到 libgdiplus。 相比之下,我们采用的其他外部依赖项,例如 icu 或 openssl,都是高质量的库。 使 libgdiplus 的功能集和质量与 .NET 堆栈的其余部分相媲美是不可行的。

通过对 NuGet 包的分析,我们观察到 System.Drawing.Common 主要用于跨平台的图像处理,例如 QR 代码生成器和文本呈现。 由于我们的跨平台图形支持不完整,我们还没有注意到大量的图形使用。 System.Drawing.Common 在非 Windows 环境中的使用通常得到 SkiaSharp ImageSharp 的良好支持。

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

建议的操作

或者,可通过将 runtimeconfig.json 文件中的 System.Drawing.EnableUnixSupportSystem.Drawing.EnableUnixSupport设置为 true 来启用对 .NET 6 中非 Windows 平台的支持:

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

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

说白了就是在非Windows平台下.net 6中默认不支持System.Drawing.Common了,想继续使用要设置运行时配置,并且以后.NET 7中这个配置也要干掉。

问题解决

又核实了一遍,确认是引用了.Net 6.0版本下的System.Drawing.Common,应该是其他人引用了6.0版本导致的。目前应用使用的是.net 5,配置是不可能修改配置的。所以,最简单的办法就是降级,将System.Drawing.Common版本降级到5.0,问题就此解决。

.NET 5或更早版本解决

docker环境下使用EPPlus 导出Excel报Gdip异常

基于dotnet官方的aspnet5的镜像构建安装libgdiplus基础镜像



转载请注明:清风亦平凡 » .net core在Linux系统报Gdip异常的问题

喜欢 (27)or分享 (0)
支付宝扫码打赏 支付宝扫码打赏 微信打赏 微信打赏
头像
发表我的评论
取消评论

CAPTCHA Image
Reload Image
表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址