翼度科技»论坛 编程开发 .net 查看内容

关于.Net 6.0 在Linux ,Docker容器中,不安装任何依赖就生成图形验证码!!

4

主题

4

帖子

12

积分

新手上路

Rank: 1

积分
12
在.Net Framework时代,我们生成验证码大多都是用System.Drawing。
在.Net 6中使用也是没有问题的。
但是,System.Drawing却依赖于Windows GDI+。
为了实现跨平台,我陷入了沉思!!

 
微软推荐使用SkiaSharp 进行替代,所以就开始了,踩坑之旅
首先,安装SkiaSharp 
编写好图形生成代码。
  1. using SkiaSharp;
  2. using System.Drawing;
  3. using System.Drawing.Text;
  4. namespace VertifyCode
  5. {
  6.     public class VerifyCodeHelper
  7.     {
  8.         private static readonly char[] Chars = { '0','1','2','3','4','5','6','8','9',
  9.                                                 'A','B','C','D','E','F','G','H','I','J','K', 'L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z' };
  10.         //private static readonly int Width = 90;
  11.         //private static readonly int Height = 35;
  12.         private static string GenCode(int num)
  13.         {
  14.             var code = string.Empty;
  15.             var r = new Random();
  16.             for (int i = 0; i < num; i++)
  17.             {
  18.                 code += Chars[r.Next(Chars.Length)].ToString();
  19.             }
  20.             return code;
  21.         }
  22.         /// <summary>
  23.         /// 获取图像数字验证码
  24.         /// </summary>
  25.         /// <returns></returns>
  26.         public static (string code, byte[] bytes) GetVerifyCode()
  27.         {
  28.             var code = GenCode(4);
  29.             int width = 128;
  30.             int height = 45;
  31.             Random random = new();
  32.             //创建bitmap位图
  33.             using SKBitmap image = new(width, height, SKColorType.Bgra8888, SKAlphaType.Premul);
  34.             //创建画笔
  35.             using SKCanvas canvas = new(image);
  36.             //填充背景颜色为白色
  37.             canvas.DrawColor(SKColors.White);
  38.             //画图片的背景噪音线
  39.             for (int i = 0; i < (width * height * 0.015); i++)
  40.             {
  41.                 using SKPaint drawStyle = new();
  42.                 drawStyle.Color = new(Convert.ToUInt32(random.Next(Int32.MaxValue)));
  43.                 canvas.DrawLine(random.Next(0, width), random.Next(0, height), random.Next(0, width), random.Next(0, height), drawStyle);
  44.             }//将文字写到画布上
  45.             using (SKPaint drawStyle = new())
  46.             {
  47.                 drawStyle.Color = SKColors.Red;
  48.                 drawStyle.TextSize = height;
  49.                 drawStyle.StrokeWidth = 1;
  50.                 float emHeight = height - (float)height * (float)0.14;
  51.                 float emWidth = ((float)width / code.Length) - ((float)width * (float)0.13);
  52.                 canvas.DrawText(code, emWidth, emHeight, drawStyle);
  53.             }
  54.             //画图片的前景噪音点
  55.             for (int i = 0; i < (width * height * 0.15); i++)
  56.             {
  57.                 image.SetPixel(random.Next(0, width), random.Next(0, height), new SKColor(Convert.ToUInt32(random.Next(Int32.MaxValue))));
  58.             }
  59.             using var img = SKImage.FromBitmap(image);
  60.             using SKData p = img.Encode(SKEncodedImageFormat.Png, 100);
  61.             return (code, p.ToArray());
  62.         }
  63.     }
  64. }
复制代码
 
在自身Windows机器上运行,哈哈,完美

 接下来,我就开始部署到Linux
部署完成后,查看日志。靠!!!!
因为咱们公司项目是部署到客户环境,客户环境同样也是内网,如果安装依赖,会非常麻烦,而且每一个客户都需要安装。所以我的目的是在不安装任何依赖的情况下,在Linux上生成图形验证码

 居然用不了,不是跨平台嘛。
于是乎,百度查询,找到了这个nuget包
SkiaSharp.NativeAssets.Linux.NoDependencies

 
原来,绘图需要很多依赖,但不是每一个Linux都会有这些,由于我们的服务器是内网,不能够在线安装,所有就使用此nuget包。避免缺少依赖。
安装,部署,然后就出现以下情况

 好家伙,字内,图有,没有字啊
 
 在我查阅资料以后,发现Linux上没有字体文件,然后我就开始怀疑人生。
因为是Docker环境,再加上没有外网,所以安装字体是个大麻烦。
但我们可以换一种思路,我提供一个字体文件,能不能让程序指定去读取这个文件
带着这个思路,我开始翻阅SkiaSharp的源码,并发现了这个类

 
字体管理类,说明是可以手动注入字体的。
然后找到了以下方法

 看来可以试试,将字体文件,读取成流,注入到程序中

 
然后再写入文字时,使用该字体示例

最终代码
  1.             //因为Linux不会有字体文件,所以读取项目中的字体文件,以便生成验证码字体
  2.             SKFont font = new SKFont(SKFontManager.Default.CreateTypeface(File.Open("msyh.ttc", FileMode.Open)));
  3.             font.Size = 38;
  4.             //将文字写到画布上
  5.             using (SKPaint drawStyle = new())
  6.             {
  7.                 drawStyle.Color = SKColors.Red;
  8.                 drawStyle.TextSize = height;
  9.                 drawStyle.StrokeWidth = 1;
  10.                 float emHeight = height - (float)height * (float)0.14;
  11.                 float emWidth = ((float)width / code.Length) - ((float)width * (float)0.13);
  12.                 canvas.DrawText(code, emWidth, emHeight, font, drawStyle);
  13.             }
复制代码
  
 字体文件从哪取,可以在C:/Windows/Fonts这个路径下复制出来,是可以兼容Linux的


接下来就是激动心,颤抖的手,我们部署到Linux(docker)下,试试。
 
 

 
OK搞定!完结撒花
 

来源:https://www.cnblogs.com/Thayou/archive/2023/09/20/17717102.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

举报 回复 使用道具