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


    在.Net Framework时代,我们生成验证码大多都是用System.Drawing。

    在.Net 6中使用也是没有问题的。

    但是,System.Drawing却依赖于Windows GDI+。

    为了实现跨平台,我陷入了沉思!!

     

    微软推荐使用SkiaSharp 进行替代,所以就开始了,踩坑之旅

    首先,安装SkiaSharp 

    编写好图形生成代码。

    复制代码
    using SkiaSharp;
    using System.Drawing;
    using System.Drawing.Text;
    
    namespace VertifyCode
    {
        public class VerifyCodeHelper
        {
            private static readonly char[] Chars = { '0','1','2','3','4','5','6','8','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' };
            //private static readonly int Width = 90;
            //private static readonly int Height = 35;
    
            private static string GenCode(int num)
            {
                var code = string.Empty;
                var r = new Random();
    
                for (int i = 0; i < num; i++)
                {
                    code += Chars[r.Next(Chars.Length)].ToString();
                }
    
                return code;
            }
            /// 
            /// 获取图像数字验证码
            /// 
            /// 
            public static (string code, byte[] bytes) GetVerifyCode()
            {
                var code = GenCode(4);
                int width = 128;
                int height = 45;
    
                Random random = new();
    
                //创建bitmap位图
                using SKBitmap image = new(width, height, SKColorType.Bgra8888, SKAlphaType.Premul);
                //创建画笔
                using SKCanvas canvas = new(image);
                //填充背景颜色为白色
                canvas.DrawColor(SKColors.White);
    
                //画图片的背景噪音线
                for (int i = 0; i < (width * height * 0.015); i++)
                {
                    using SKPaint drawStyle = new();
                    drawStyle.Color = new(Convert.ToUInt32(random.Next(Int32.MaxValue)));
    
                    canvas.DrawLine(random.Next(0, width), random.Next(0, height), random.Next(0, width), random.Next(0, height), drawStyle);
                }//将文字写到画布上
                using (SKPaint drawStyle = new())
                {
                    drawStyle.Color = SKColors.Red;
                    drawStyle.TextSize = height;
                    drawStyle.StrokeWidth = 1;
    
                    float emHeight = height - (float)height * (float)0.14;
                    float emWidth = ((float)width / code.Length) - ((float)width * (float)0.13);
                    canvas.DrawText(code, emWidth, emHeight, drawStyle);
                }
    
                //画图片的前景噪音点
                for (int i = 0; i < (width * height * 0.15); i++)
                {
                    image.SetPixel(random.Next(0, width), random.Next(0, height), new SKColor(Convert.ToUInt32(random.Next(Int32.MaxValue))));
                }
    
                using var img = SKImage.FromBitmap(image);
                using SKData p = img.Encode(SKEncodedImageFormat.Png, 100);
                return (code, p.ToArray());
            }
        }
    }
    复制代码

     

    在自身Windows机器上运行,哈哈,完美

     接下来,我就开始部署到Linux

    部署完成后,查看日志。靠!!!!

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

     居然用不了,不是跨平台嘛。

    于是乎,百度查询,找到了这个nuget包

    SkiaSharp.NativeAssets.Linux.NoDependencies

     

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

    安装,部署,然后就出现以下情况

     好家伙,字内,图有,没有字啊

     

     在我查阅资料以后,发现Linux上没有字体文件,然后我就开始怀疑人生。

    因为是Docker环境,再加上没有外网,所以安装字体是个大麻烦。

    但我们可以换一种思路,我提供一个字体文件,能不能让程序指定去读取这个文件

    带着这个思路,我开始翻阅SkiaSharp的源码,并发现了这个类

     

    字体管理类,说明是可以手动注入字体的。

    然后找到了以下方法

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

     

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

    最终代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    //因为Linux不会有字体文件,所以读取项目中的字体文件,以便生成验证码字体
    SKFont font = new SKFont(SKFontManager.Default.CreateTypeface(File.Open("msyh.ttc", FileMode.Open)));
    font.Size = 38;
    //将文字写到画布上
    using (SKPaint drawStyle = new())
    {
        drawStyle.Color = SKColors.Red;
        drawStyle.TextSize = height;
        drawStyle.StrokeWidth = 1;
     
        float emHeight = height - (float)height * (float)0.14;
        float emWidth = ((float)width / code.Length) - ((float)width * (float)0.13);
        canvas.DrawText(code, emWidth, emHeight, font, drawStyle);
    }

      

     字体文件从哪取,可以在C:/Windows/Fonts这个路径下复制出来,是可以兼容Linux的

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

     

     

     

    OK搞定!完结撒花

     

  • 相关阅读:
    【Android】-- 按钮(复选框CheckBox、开关按钮Switch、单选按钮RadioButton)
    TCS34725颜色感应识别模块
    【python】(二十) python装饰器
    聊聊如何利用管道模式来进行业务编排(下篇)
    09_SpingBoot 集成Dubbo
    AOP
    [附源码]计算机毕业设计Springboot大学生志愿者服务管理系统
    嵌入式快速入门学习笔记-Framebuffer
    [深度学习][原创]让yolov6-0.1.0支持yolov5的txt读取数据集模式
    UE5.1 + Android 环境搭建
  • 原文地址:https://www.cnblogs.com/Thayou/p/17717102.html