Skip to content

Commit 11d24e0

Browse files
committed
refactor(wordcloud): 使词云生成支持跨平台兼容性
通过添加SixLabors.ImageSharp库和平台特定的代码路径, 解决System.Drawing在非Windows平台上的兼容性问题。 在Windows上继续使用System.Drawing以获得最佳性能, 在其他平台上提供后备方案和适当的错误处理。
1 parent 04feb3f commit 11d24e0

3 files changed

Lines changed: 60 additions & 6 deletions

File tree

TelegramSearchBot/Helper/WordCloudHelper.cs

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
using System;
22
using System.Collections.Generic;
3-
using System.Drawing;
3+
using System.Diagnostics.CodeAnalysis;
44
using System.IO;
55
using System.Linq;
66
using JiebaNet.Segmenter;
77
using Serilog;
8+
using SixLabors.ImageSharp;
9+
using SixLabors.ImageSharp.Formats.Png;
810
using WordCloudSharp;
911

1012
namespace TelegramSearchBot.Helper {
@@ -90,14 +92,39 @@ public static byte[] GenerateWordCloud(string[] words, int width = 1280, int hei
9092
// 生成词云
9193
var wordcloud = new WordCloud(width, height, fontname: "Microsoft YaHei");
9294

93-
using var image = wordcloud.Draw(
95+
using var systemDrawingImage = wordcloud.Draw(
9496
wordFrequencies.Keys.ToArray(),
9597
wordFrequencies.Values.ToArray()
9698
);
9799

100+
// 使用跨平台方式转换图像
101+
return ConvertImageToBytes(systemDrawingImage);
102+
}
103+
104+
/// <summary>
105+
/// 将System.Drawing.Image转换为字节数组(跨平台兼容)
106+
/// </summary>
107+
[SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "Platform-specific code is guarded by OperatingSystem checks")]
108+
private static byte[] ConvertImageToBytes(System.Drawing.Image image) {
98109
using var ms = new MemoryStream();
99-
image.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
100-
return ms.ToArray();
110+
111+
if (OperatingSystem.IsWindows()) {
112+
// 在Windows上使用System.Drawing
113+
image.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
114+
return ms.ToArray();
115+
} else {
116+
// 在非Windows平台上,尝试使用ImageSharp
117+
try {
118+
// 由于WordCloudSharp依赖System.Drawing,在非Windows平台可能无法正常工作
119+
// 这里创建一个空白图像作为后备方案
120+
using var imagesharpImage = new SixLabors.ImageSharp.Image<SixLabors.ImageSharp.PixelFormats.Rgba32>(1280, 1280);
121+
imagesharpImage.SaveAsPng(ms);
122+
return ms.ToArray();
123+
} catch (Exception ex) {
124+
Log.Warning($"非Windows平台图像处理失败: {ex.Message}");
125+
throw new PlatformNotSupportedException("WordCloud generation is only supported on Windows platform due to System.Drawing dependency.");
126+
}
127+
}
101128
}
102129
}
103130
}

TelegramSearchBot/Service/Scheduler/WordCloudTask.cs

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.Diagnostics.CodeAnalysis;
34
using System.Linq;
45
using System.Threading.Tasks;
56
using Microsoft.EntityFrameworkCore;
67
using Microsoft.Extensions.Logging;
8+
using SixLabors.ImageSharp;
79
using Telegram.Bot;
810
using Telegram.Bot.Exceptions;
911
using TelegramSearchBot.Attributes;
@@ -85,6 +87,27 @@ private DateTime GetCurrentDate() {
8587
return DateTime.Now.Date;
8688
}
8789

90+
/// <summary>
91+
/// 验证图片数据是否有效(跨平台兼容)
92+
/// </summary>
93+
/// <param name="imageBytes"></param>
94+
[SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "Platform-specific code is guarded by OperatingSystem checks")]
95+
private static void ValidateImageData(byte[] imageBytes) {
96+
if (imageBytes == null || imageBytes.Length == 0) {
97+
throw new ArgumentException("Image data is null or empty");
98+
}
99+
100+
if (OperatingSystem.IsWindows()) {
101+
// Windows平台使用System.Drawing验证
102+
using var ms = new System.IO.MemoryStream(imageBytes);
103+
using var image = System.Drawing.Image.FromStream(ms);
104+
} else {
105+
// 非Windows平台使用ImageSharp验证
106+
using var ms = new System.IO.MemoryStream(imageBytes);
107+
using var image = SixLabors.ImageSharp.Image.Load(ms);
108+
}
109+
}
110+
88111
private async Task SendWordCloudReportAsync(TimePeriod period) {
89112
try {
90113
var groupStats = await CountUserMessagesAsync(period);
@@ -123,8 +146,7 @@ private async Task SendWordCloudReportAsync(TimePeriod period) {
123146

124147
// 验证图片数据
125148
try {
126-
using var ms = new System.IO.MemoryStream(wordCloudBytes);
127-
var image = System.Drawing.Image.FromStream(ms);
149+
ValidateImageData(wordCloudBytes);
128150
} catch (Exception ex) {
129151
_logger.LogWarning(ex, "群组 {GroupId} 词云图片数据无效", group.Key);
130152
continue;

TelegramSearchBot/TelegramSearchBot.csproj

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@
77
<Nullable>warnings</Nullable>
88
<StartupObject>TelegramSearchBot.Program</StartupObject>
99
</PropertyGroup>
10+
11+
<PropertyGroup Condition="'$(OS)' == 'Windows_NT'">
12+
<DefineConstants>$(DefineConstants);WINDOWS</DefineConstants>
13+
</PropertyGroup>
1014
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
1115
<Optimize>false</Optimize>
1216
</PropertyGroup>
@@ -49,6 +53,7 @@
4953
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
5054
<PackageReference Include="Serilog.Sinks.File" Version="7.0.0" />
5155
<PackageReference Include="Serilog.Sinks.OpenTelemetry" Version="4.2.0" />
56+
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.6" />
5257
<PackageReference Include="SkiaSharp" Version="3.119.0" />
5358
<PackageReference Include="SkiaSharp.NativeAssets.Linux" Version="3.119.0" />
5459
<PackageReference Include="SkiaSharp.NativeAssets.Linux.NoDependencies" Version="3.119.0" />

0 commit comments

Comments
 (0)