背景
.net core
应用中使用了Excel
文件导出,发现Excel
导出失败,导出的操作出现了异常。看了一下是Gdip
的这个异常。这个异曾经见到过,记得也很快解决了,不晓得为什么又会出现呢?仔细看了一下,详细错误还是有点差别。经过确认上一次安装的libc6-dev
、libgdiplus
是存在的,并没有丢失或者损坏。
根据异常信息,基本可以确定是引用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
操作系统编译引用代码时,平台分析器会发出编译时警告。 此外,除非设置了配置选项,否则将引发以下运行时异常:
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,000
行 C
代码,大部分未经测试,而且缺少很多功能。 libgdiplus
还具有许多用于图像处理和文本呈现的外部依赖项,例如 cairo
、pango
和其他本机库。 这些依赖项使得维护和交付组件更具挑战性。 自从包含 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异常的问题