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

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

时间:2023-09-20 23:33:45浏览次数:52  
标签:code drawStyle 6.0 float height width Linux using Net

在.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;
        }
        /// <summary>
        /// 获取图像数字验证码
        /// </summary>
        /// <returns></returns>
        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搞定!完结撒花

标签:code,drawStyle,6.0,float,height,width,Linux,using,Net
From: https://www.cnblogs.com/chinasoft/p/17718816.html

相关文章

  • Linux namespace之:uts namespace
    Linuxnamespace系列文章理解utsnamespaceuts(UNIXTime-SharingSystem)namespace可隔离hostname和NISDomainname资源,使得一个宿主机可拥有多个主机名或DomainName。换句话说,可让不同namespace中的进程看到不同的主机名。例如,使用unshare命令(较新版本Linux内核还支持n......
  • Linux namespace之:mount namespace
    Linuxnamespace系列文章理解mountnamespace用户通常使用mount命令来挂载普通文件系统,但实际上mount能挂载的东西非常多,甚至连现在功能完善的Linux系统,其内核的正常运行也都依赖于挂载功能,比如挂载根文件系统/。其实所有的挂载功能和挂载信息都由内核负责提供和维护,mount命令......
  • Linux namespace之:pid namespace
    Linuxnamespace系列文章理解pidnamespacePIDnamespace表示隔离一个具有独立PID的运行环境。在每一个pidnamespace中,进程的pid都从1开始,且和其他pidnamespace中的PID互不影响。这意味着,不同pidnamespace中可以有相同的PID值。因为PIDnamespace中的PID是独立的,每一个PID......
  • Linux namespace之:network namespace
    Linuxnamespace系列文章理解networknamespacenetworknamespace用来隔离网络环境,在networknamespace中,网络设备、端口、套接字、网络协议栈、路由表、防火墙规则等都是独立的。因networknamespace中具有独立的网络协议栈,因此每个networknamespace中都有一个lo接口,但lo接......
  • 基于Unet+opencv实现天空对象的分割、替换和美化
      传统图像处理算法进行“天空分割”存在精度问题且调参复杂,无法很好地应对云雾、阴霾等情况;本篇文章分享的“基于Unet+opencv实现天空对象的分割、替换和美化”,较好地解决了该问题,包括以下内容:1、基于Unet语义分割的基本原理、环境构建、参数调节等2、一种有效的天空分割数......
  • 测试linux代码运行时间
    1. 前置知识  (1)gettid内核给线程(轻量级进程)分配的进程id,全局(所有进程中)唯一;  (2)pthread_self()是在用户态实现的,获取的是相对于进程的线程控制块的首地址,只是在当前进程空间中是唯一的。不能保证同一进程先后多个线程具有不同的id。(当前一个线程结束其生命周期,进程又新......
  • Linux Namespace
    1LinuxNamespace概述Namespace是对全局系统资源的一种封装隔离,使得处于不同namespace的进程拥有独立的全局资源,改变一个namespace中的系统资源只会影响当前namespace里的进程,对其他namespace中的进程没有影响。1.1Linux内核支持的namespaces目前,Linux内核里面实现了7种不同类型的......
  • 关于Kubernetes-v1.23.6-资源调度-Deployment-版本的回滚
    先看一下,当前笔者这里的k8s环境,主要是deployment,rs,pods相关的信息[root@k8s-masterqq-5201351]#kubectlgetdeployNAMEREADYUP-TO-DATEAVAILABLEAGEnginx-deploy3/33324h[root@k8s-masterqq-5201351]#[root@k8s-......
  • Metasploitable-Linux靶机配置
    Metasploitable和kali是课上下载好的。直接打开进入欢迎界面用默认账号登录了之后,修改root密码(sudopasswdroot),登录root账号,查看本机IP(ifconfig)切换到kali,把kali的IP改为192.168.72.129,且能ping通192.168.72.131在kali的浏览器中输入靶机的IP,可以看到靶机的界面......
  • linux中grep与find的区别,Linux三剑客【grep、sed和awk】
    在使用linux时,经常需要进行文件查找。其中查找的命令主要有find和grep。两个命令是有区的。区别:(1)find命令是根据文件的属性进行查找,如文件名,文件大小,所有者,所属组,是否为空,访问时间,修改时间等。(2)grep是根据文件的内容进行查找,会对文件的每一行按照给定的模式(patter)......