关于.Net 6.0 在Linux ,Docker容器中,不安装任何依赖就生成图形验证码!!!!!!!!!!!
<p>在.Net Framework时代,我们生成验证码大多都是用System.Drawing。</p><p>在.Net 6中使用也是没有问题的。</p>
<p>但是,System.Drawing却依赖于Windows GDI+。</p>
<p>为了实现跨平台,我陷入了沉思!!</p>
<p><img src="https://img2023.cnblogs.com/blog/1509333/202309/1509333-20230920130534646-597607606.png"></p>
<p> </p>
<p>微软推荐使用SkiaSharp 进行替代,所以就开始了,踩坑之旅</p>
<p>首先,安装SkiaSharp </p>
<p>编写好图形生成代码。</p>
<div class="cnblogs_code">
<pre> <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> VerifyCodeHelper
{
</span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span><span style="color: rgba(0, 0, 0, 1)"> SKFont _font;
</span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">object</span> _lock = <span style="color: rgba(0, 0, 255, 1)">new</span> <span style="color: rgba(0, 0, 255, 1)">object</span><span style="color: rgba(0, 0, 0, 1)">();
</span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">readonly</span> <span style="color: rgba(0, 0, 255, 1)">char</span>[] Chars = { <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">0</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">1</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">2</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">3</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">4</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">5</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">6</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">8</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">9</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">A</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">B</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">C</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">D</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">E</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">F</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">G</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">H</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">I</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">J</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">K</span><span style="color: rgba(128, 0, 0, 1)">'</span>, <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">L</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">M</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">N</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">O</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">P</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">Q</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">R</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">S</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">T</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">U</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">V</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">W</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">X</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">Y</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">Z</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)"> };
</span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">string</span> GenCode(<span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> num)
{
</span><span style="color: rgba(0, 0, 255, 1)">var</span> code = <span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">.Empty;
</span><span style="color: rgba(0, 0, 255, 1)">var</span> r = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Random();
</span><span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">int</span> i = <span style="color: rgba(128, 0, 128, 1)">0</span>; i < num; i++<span style="color: rgba(0, 0, 0, 1)">)
{
code </span>+=<span style="color: rgba(0, 0, 0, 1)"> Chars.ToString();
}
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> code;
}
</span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)"><summary></span>
<span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 获取图像数字验证码
</span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)"></summary></span>
<span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)"><returns></returns></span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> (<span style="color: rgba(0, 0, 255, 1)">string</span> code, <span style="color: rgba(0, 0, 255, 1)">byte</span><span style="color: rgba(0, 0, 0, 1)">[] bytes) GetVerifyCode()
{
</span><span style="color: rgba(0, 0, 255, 1)">var</span> code = GenCode(<span style="color: rgba(128, 0, 128, 1)">4</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">int</span> width = <span style="color: rgba(128, 0, 128, 1)">128</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">int</span> height = <span style="color: rgba(128, 0, 128, 1)">45</span><span style="color: rgba(0, 0, 0, 1)">;
Random random </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)">();
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">创建bitmap位图</span>
<span style="color: rgba(0, 0, 255, 1)">using</span> SKBitmap image = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)">(width, height, SKColorType.Bgra8888, SKAlphaType.Premul);
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">创建画笔</span>
<span style="color: rgba(0, 0, 255, 1)">using</span> SKCanvas canvas = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)">(image);
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">填充背景颜色为白色</span>
<span style="color: rgba(0, 0, 0, 1)"> canvas.DrawColor(SKColors.White);
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">画图片的背景噪音线</span>
<span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">int</span> i = <span style="color: rgba(128, 0, 128, 1)">0</span>; i < (width * height * <span style="color: rgba(128, 0, 128, 1)">0.015</span>); i++<span style="color: rgba(0, 0, 0, 1)">)
{
</span><span style="color: rgba(0, 0, 255, 1)">using</span> SKPaint drawStyle = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)">();
drawStyle.Color </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)">(Convert.ToUInt32(random.Next(Int32.MaxValue)));
canvas.DrawLine(random.Next(</span><span style="color: rgba(128, 0, 128, 1)">0</span>, width), random.Next(<span style="color: rgba(128, 0, 128, 1)">0</span>, height), random.Next(<span style="color: rgba(128, 0, 128, 1)">0</span>, width), random.Next(<span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">, height), drawStyle);
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">将文字写到画布上</span>
<span style="color: rgba(0, 0, 255, 1)">using</span> (SKPaint drawStyle = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)">())
{
drawStyle.Color </span>=<span style="color: rgba(0, 0, 0, 1)"> SKColors.Red;
drawStyle.TextSize </span>=<span style="color: rgba(0, 0, 0, 1)"> height;
drawStyle.StrokeWidth </span>= <span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">float</span> emHeight = height - (<span style="color: rgba(0, 0, 255, 1)">float</span>)height * (<span style="color: rgba(0, 0, 255, 1)">float</span>)<span style="color: rgba(128, 0, 128, 1)">0.14</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">float</span> emWidth = ((<span style="color: rgba(0, 0, 255, 1)">float</span>)width / code.Length) - ((<span style="color: rgba(0, 0, 255, 1)">float</span>)width * (<span style="color: rgba(0, 0, 255, 1)">float</span>)<span style="color: rgba(128, 0, 128, 1)">0.13</span><span style="color: rgba(0, 0, 0, 1)">);
canvas.DrawText(code, emWidth, emHeight, drawStyle);
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">画图片的前景噪音点</span>
<span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">int</span> i = <span style="color: rgba(128, 0, 128, 1)">0</span>; i < (width * height * <span style="color: rgba(128, 0, 128, 1)">0.15</span>); i++<span style="color: rgba(0, 0, 0, 1)">)
{
image.SetPixel(random.Next(</span><span style="color: rgba(128, 0, 128, 1)">0</span>, width), random.Next(<span style="color: rgba(128, 0, 128, 1)">0</span>, height), <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> SKColor(Convert.ToUInt32(random.Next(Int32.MaxValue))));
}
</span><span style="color: rgba(0, 0, 255, 1)">using</span> <span style="color: rgba(0, 0, 255, 1)">var</span> img =<span style="color: rgba(0, 0, 0, 1)"> SKImage.FromBitmap(image);
</span><span style="color: rgba(0, 0, 255, 1)">using</span> SKData p = img.Encode(SKEncodedImageFormat.Png, <span style="color: rgba(128, 0, 128, 1)">100</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> (code, p.ToArray());
}
}</span></pre>
</div>
<p> </p>
<p> </p>
<p> </p>
<p>在自身Windows机器上运行,哈哈,完美</p>
<p><img src="https://img2023.cnblogs.com/blog/1509333/202309/1509333-20230920131003416-2081502143.png"></p>
<p> 接下来,我就开始部署到Linux</p>
<p>部署完成后,查看日志。靠!!!!</p>
<p><span style="font-size: 18pt; color: rgba(255, 0, 0, 1)"><strong>因为咱们公司项目是部署到客户环境,客户环境同样也是内网,如果安装依赖,会非常麻烦,而且每一个客户都需要安装。所以我的目的是在不安装任何依赖的情况下,在Linux上生成图形验证码</strong></span><img src="https://img2023.cnblogs.com/blog/1509333/202309/1509333-20230920131110946-887690107.png"></p>
<p><span style="font-size: 16px; color: rgba(255, 0, 0, 1)"> 居然用不了,不是跨平台嘛。</span></p>
<p><span style="font-size: 16px; color: rgba(255, 0, 0, 1)">于是乎,百度查询,找到了这个nuget包</span></p>
<p><span style="font-size: 16px; color: rgba(255, 0, 0, 1)">SkiaSharp.NativeAssets.Linux.NoDependencies</span></p>
<p><img src="https://img2023.cnblogs.com/blog/1509333/202309/1509333-20230920131256851-615411272.png"></p>
<p> </p>
<p><span style="color: rgba(255, 0, 0, 1); font-size: 16px">原来,绘图需要很多依赖,但不是每一个Linux都会有这些,由于我们的服务器是内网,不能够在线安装,所有就使用此nuget包。避免缺少依赖。</span></p>
<p><span style="color: rgba(255, 0, 0, 1); font-size: 16px">安装,部署,然后就出现以下情况</span></p>
<p><img src="https://img2023.cnblogs.com/blog/1509333/202309/1509333-20230920131716789-1466777809.png"></p>
<p> 好家伙,字内,图有,没有字啊</p>
<p> </p>
<p><span style="color: rgba(255, 0, 0, 1); font-size: 18px"> 在我查阅资料以后,发现Linux上没有字体文件,然后我就开始怀疑人生。</span></p>
<p><span style="color: rgba(255, 0, 0, 1); font-size: 18px">因为是Docker环境,再加上没有外网,所以安装字体是个大麻烦。</span></p>
<p><span style="color: rgba(255, 0, 0, 1); font-size: 18px">但我们可以换一种思路,我提供一个字体文件,能不能让程序指定去读取这个文件</span></p>
<p><span style="color: rgba(255, 0, 0, 1); font-size: 18px">带着这个思路,我开始翻阅SkiaSharp的源码,并发现了这个类</span></p>
<p><img src="https://img2023.cnblogs.com/blog/1509333/202309/1509333-20230920131958955-1363711886.png"></p>
<p> </p>
<p>字体管理类,说明是可以手动注入字体的。</p>
<p>然后找到了以下方法</p>
<p><img src="https://img2023.cnblogs.com/blog/1509333/202309/1509333-20230920132023979-395402357.png"></p>
<p> 看来可以试试,将字体文件,读取成流,注入到程序中</p>
<p><img src="https://img2023.cnblogs.com/blog/1509333/202309/1509333-20230920132055790-1625065579.png"></p>
<p> </p>
<p>然后再写入文字时,使用该字体示例</p>
<p><img src="https://img2023.cnblogs.com/blog/1509333/202309/1509333-20230920132128082-964088912.png"></p>
<p>最终代码</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> SkiaSharp;
</span><span style="color: rgba(0, 0, 255, 1)">namespace</span><span style="color: rgba(0, 0, 0, 1)"> VertifyCode
{
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> VerifyCodeHelper
{
</span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span><span style="color: rgba(0, 0, 0, 1)"> SKFont _font;
</span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">object</span> _lock = <span style="color: rgba(0, 0, 255, 1)">new</span> <span style="color: rgba(0, 0, 255, 1)">object</span><span style="color: rgba(0, 0, 0, 1)">();
</span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">readonly</span> <span style="color: rgba(0, 0, 255, 1)">char</span>[] Chars = { <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">0</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">1</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">2</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">3</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">4</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">5</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">6</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">8</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">9</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">A</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">B</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">C</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">D</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">E</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">F</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">G</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">H</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">I</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">J</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">K</span><span style="color: rgba(128, 0, 0, 1)">'</span>, <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">L</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">M</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">N</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">O</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">P</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">Q</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">R</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">S</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">T</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">U</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">V</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">W</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">X</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">Y</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">Z</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)"> };
</span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)"><summary></span>
<span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 渲染字体
</span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)"></summary></span>
<span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span><span style="color: rgba(0, 0, 0, 1)"> SKFont VerifyCodeFont
{
</span><span style="color: rgba(0, 0, 255, 1)">get</span><span style="color: rgba(0, 0, 0, 1)">
{
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (_font == <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">)
{
</span><span style="color: rgba(0, 0, 255, 1)">lock</span><span style="color: rgba(0, 0, 0, 1)"> (_lock)
{
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (_font == <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">)
{
</span><span style="color: rgba(0, 0, 255, 1)">using</span> (FileStream Fontfile = File.Open(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">DejaVuSans.ttf</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">, FileMode.Open))
{
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">因为Linux不会有字体文件,所以读取项目中的字体文件,以便生成验证码字体</span>
_font = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> SKFont(SKFontManager.Default.CreateTypeface(Fontfile));
_font.Size </span>= <span style="color: rgba(128, 0, 128, 1)">37</span><span style="color: rgba(0, 0, 0, 1)">;
}
}
}
}
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> _font;
}
}
</span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">string</span> GenCode(<span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> num)
{
</span><span style="color: rgba(0, 0, 255, 1)">var</span> code = <span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">.Empty;
</span><span style="color: rgba(0, 0, 255, 1)">var</span> r = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Random();
</span><span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">int</span> i = <span style="color: rgba(128, 0, 128, 1)">0</span>; i < num; i++<span style="color: rgba(0, 0, 0, 1)">)
{
code </span>+=<span style="color: rgba(0, 0, 0, 1)"> Chars.ToString();
}
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> code;
}
</span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)"><summary></span>
<span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 获取图像数字验证码
</span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)"></summary></span>
<span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)"><returns></returns></span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> (<span style="color: rgba(0, 0, 255, 1)">string</span> code, <span style="color: rgba(0, 0, 255, 1)">byte</span><span style="color: rgba(0, 0, 0, 1)">[] bytes) GetVerifyCode()
{
</span><span style="color: rgba(0, 0, 255, 1)">var</span> code = GenCode(<span style="color: rgba(128, 0, 128, 1)">4</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">int</span> width = <span style="color: rgba(128, 0, 128, 1)">128</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">int</span> height = <span style="color: rgba(128, 0, 128, 1)">45</span><span style="color: rgba(0, 0, 0, 1)">;
Random random </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)">();
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">创建bitmap位图</span>
<span style="color: rgba(0, 0, 255, 1)">using</span> SKBitmap image = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)">(width, height, SKColorType.Bgra8888, SKAlphaType.Premul);
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">创建画笔</span>
<span style="color: rgba(0, 0, 255, 1)">using</span> SKCanvas canvas = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)">(image);
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">填充背景颜色为白色</span>
<span style="color: rgba(0, 0, 0, 1)"> canvas.DrawColor(SKColors.White);
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">画图片的背景噪音线</span>
<span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">int</span> i = <span style="color: rgba(128, 0, 128, 1)">0</span>; i < (width * height * <span style="color: rgba(128, 0, 128, 1)">0.015</span>); i++<span style="color: rgba(0, 0, 0, 1)">)
{
</span><span style="color: rgba(0, 0, 255, 1)">using</span> SKPaint drawStyle = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)">();
drawStyle.Color </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)">(Convert.ToUInt32(random.Next(Int32.MaxValue)));
canvas.DrawLine(random.Next(</span><span style="color: rgba(128, 0, 128, 1)">0</span>, width), random.Next(<span style="color: rgba(128, 0, 128, 1)">0</span>, height), random.Next(<span style="color: rgba(128, 0, 128, 1)">0</span>, width), random.Next(<span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">, height), drawStyle);
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">将文字写到画布上</span>
<span style="color: rgba(0, 0, 255, 1)">using</span> (SKPaint drawStyle = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)">())
{
drawStyle.Color </span>=<span style="color: rgba(0, 0, 0, 1)"> SKColors.Red;
drawStyle.TextSize </span>=<span style="color: rgba(0, 0, 0, 1)"> height;
drawStyle.StrokeWidth </span>= <span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">float</span> emHeight = height - (<span style="color: rgba(0, 0, 255, 1)">float</span>)height * (<span style="color: rgba(0, 0, 255, 1)">float</span>)<span style="color: rgba(128, 0, 128, 1)">0.14</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">float</span> emWidth = ((<span style="color: rgba(0, 0, 255, 1)">float</span>)width / code.Length) - ((<span style="color: rgba(0, 0, 255, 1)">float</span>)width * (<span style="color: rgba(0, 0, 255, 1)">float</span>)<span style="color: rgba(128, 0, 128, 1)">0.13</span><span style="color: rgba(0, 0, 0, 1)">);
canvas.DrawText(code, emWidth, emHeight, VerifyCodeFont, drawStyle);
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">画图片的前景噪音点</span>
<span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">int</span> i = <span style="color: rgba(128, 0, 128, 1)">0</span>; i < (width * height * <span style="color: rgba(128, 0, 128, 1)">0.15</span>); i++<span style="color: rgba(0, 0, 0, 1)">)
{
image.SetPixel(random.Next(</span><span style="color: rgba(128, 0, 128, 1)">0</span>, width), random.Next(<span style="color: rgba(128, 0, 128, 1)">0</span>, height), <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> SKColor(Convert.ToUInt32(random.Next(Int32.MaxValue))));
}
</span><span style="color: rgba(0, 0, 255, 1)">using</span> <span style="color: rgba(0, 0, 255, 1)">var</span> img =<span style="color: rgba(0, 0, 0, 1)"> SKImage.FromBitmap(image);
</span><span style="color: rgba(0, 0, 255, 1)">using</span> SKData p = img.Encode(SKEncodedImageFormat.Png, <span style="color: rgba(128, 0, 128, 1)">100</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> (code, p.ToArray());
}
}
}</span></pre>
</div>
<p> </p>
<p> </p>
<p> 字体文件从哪取,可以在C:/Windows/Fonts这个路径下复制出来,是可以兼容Linux的</p>
<p><img src="https://img2023.cnblogs.com/blog/1509333/202309/1509333-20230920132227167-1499092076.png"></p>
<p><img src="https://img2023.cnblogs.com/blog/1509333/202309/1509333-20230920132251740-543526937.png"></p>
<p>接下来就是激动心,颤抖的手,我们部署到Linux(docker)下,试试。</p>
<p> </p>
<p> </p>
<p><img src="https://img2023.cnblogs.com/blog/1509333/202309/1509333-20230920132606334-768163036.png"></p>
<p> </p>
<p><span style="font-size: 18pt; color: rgba(255, 0, 0, 1)"><strong>OK搞定!完结撒花</strong></span></p>
<p> </p><br><br>
来源:https://www.cnblogs.com/Thayou/p/17717102.html
頁:
[1]