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

Linux ,Docker容器,验证码,图形 · 浏览次数 : 11

小编点评

**代码介绍:** 该代码提供了一个 .Net 6 应用程序的方法,用于生成跨平台图形验证码。它使用 SkiaSharp 库来实现绘制图形和文本的功能。 **代码步骤:** 1. 获取代码中的字符数组。 2. 创建一个 SkiaSharp 图像对象。 3. 设置图像大小和背景颜色。 4. 在图像中绘制背景噪音线。 5. 在图像中绘制文字。 6. 在图像中绘制前景噪音点。 7. 将图像转换为 PNG 格式并编码为字节数组。 8. 返回生成的验证码和字节数组。 **问题和解决方案:** 1. **跨平台问题:** 由于 SkiaSharp 使用 GDI+ 库,而 Linux 上没有类似的库,因此代码无法直接使用 SkiaSharp 在 Linux 上运行。 解决方案:使用 SkiaSharp NativeAssets 库的字体管理类来加载字体文件并将其注入代码中。 2. **字体文件路径问题:** 由于 Linux 上可能没有与项目中的字体文件相同的路径,因此代码需要获取字体文件并将其加载进来。 解决方案:在代码中读取字体文件并将其加载到 SkiaSharp 中。 3. **跨平台兼容性问题:** 由于 SkiaSharp 库依赖 Windows GDI+,因此代码可能无法在所有平台上运行。 解决方案:使用 .NET Framework 的 System.Drawing 库来实现图形绘制功能,该库可以跨平台运行。 **最终结果:** 该代码能够跨平台生成图形验证码,并在 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;
        }
        /// <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的源码,并发现了这个类

 

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

然后找到了以下方法

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

 

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

最终代码

            //因为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搞定!完结撒花

 

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

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

在.Net Framework时代,我们生成验证码大多都是用System.Drawing。 在.Net 6中使用也是没有问题的。 但是,System.Drawing却依赖于Windows GDI+。 为了实现跨平台,我陷入了沉思!! 微软推荐使用SkiaSharp 进行替代,所以就开始了,踩坑之旅

[转帖]CONNTRACK_MAX和HASHSIZE

关于linux中的CONNTRACK_MAX和HASHSIZE要注意的地方 如果在压力测试的时候,并发数增大,但无法完成测试,可以尝试调整下参数: vi /etc/sysctl.conf 在kernel2.6之前的添加项: net.ipv4.netfilter.ip_conntrack_max =

.NET无侵入自动化探针原理和主流实现

## 前言 最近,我在微信公众号和博客园分享了一篇关于[.NET微服务系统迁移至.NET 6.0的故事](https://www.cnblogs.com/InCerry/p/microservice-migration-net-6.html)的文章,引起了许多读者的关注。其中,许多人对基于 Open

C#的基于.net framework的Dll模块编程(二) - 编程手把手系列文章

今天继续这个系列博文的编写。接上次的篇幅,这次介绍关于C#的Dll类库的创建的内容。因为是手把手系列,所以对于需要入门的朋友来说还是挺好的,下面开始咯: 一、新建Dll类库; 这里直接创建例子的Dll类库项目,至于项目文件目录的存放布局后面的例子中会介绍。 在解决方案资源管理器上鼠标右键,选择“添加

.NET应用如何防止被反编译

前言 前段时间分享了两篇关于.NET反编译相关的文章,然后文章留言区就有小伙伴提问:如何防止被反编译?因此本篇文章我们就来讲讲.NET应用如何防止被反编译。.NET反编译相关的文章可以看如下文章: 4款免费且实用的.NET反编译工具 .NET反编译神器ILSpy怎么用? .NET应用如何防止被反编译

.NET周报【10月第2期 2022-10-17】

主题 宣布 .NET 7 发布候选版本 2 - .NET Blog https://devblogs.microsoft.com/dotnet/announcing-dotnet-7-rc-2/ .NET 7 RC2 已经发布。 .NET 7 RC2 已经发布。 文章除了链接到过去关于.NET 7的

基于Admin.NET框架的前端的一些改进和代码生成处理(2)

在上篇随笔《基于Admin.NET框架的前端的一些改进和代码生成处理(1)》中大致介绍了一些关于对Admin.NET框架的前端的改造工作,主要目的就是希望能够增加代码的简洁和可读性,以及利用代码生成工具来快速生成相关的代码,从而减少开发过程中的繁琐问题。本篇随笔继续探讨一下,对其中一些模块功能进行一些修改调整。

关于Word转PDF的几种实现方案

在.NET中,你可以使用Microsoft.Office.Interop.Word库来进行Word到PDF的转换。这是一个示例代码,但请注意这需要在你的系统上安装Microsoft Office。 在开始前,你需要添加对Microsoft.Office.Interop.Word的引用,步骤如下: 在

[转帖]关于gdb相关的几个工具的说明

https://phpor.net/blog/post/846 使用rpm命名查看gdb的rpm包,主要由下面几个程序:/usr/bin/gcore/usr/bin/gdb/usr/bin/gdbserver/usr/bin/gdbtui/usr/bin/gstack 其中:gcore 是生成cor

关于Async、Await的一些知识点

在ASP.NET Core中,当一个HTTP请求到达服务器时,它会被分配给线程池中的一个线程来处理。该线程会执行相应的Controller方法。 如果这个方法是一个异步方法并且使用了await关键字,那么在await的代码执行完毕之前,这个线程会被释放回线程池,可以用来处理其他的HTTP请求。 当a