ImageSharp一個專註於NetCore平臺圖像處理的開源項目

来源:http://www.cnblogs.com/wangrudong003/archive/2017/10/12/7656842.html
-Advertisement-
Play Games

今天大家分享的是一個專註於NetCore平臺圖像處理的開源項目,老實說為這篇文章取名字想了5分鐘,可能是詞窮亦或是想更好的表達出這款開源項目的作用;這個項目在圖像處理方面有很多功能,如:縮放,裁剪,繪畫,組合圖片等;今天主要講的是用她怎麼來繪圖和生成驗證碼的實際例子。 簡單介紹ImageSharp ...


今天大家分享的是一個專註於NetCore平臺圖像處理的開源項目,老實說為這篇文章取名字想了5分鐘,可能是詞窮亦或是想更好的表達出這款開源項目的作用;這個項目在圖像處理方面有很多功能,如:縮放,裁剪,繪畫,組合圖片等;今天主要講的是用她怎麼來繪圖和生成驗證碼的實際例子。

  • 簡單介紹ImageSharp
  • 試試畫兩條線(實線和虛線)
  • 生成個縮略圖
  • 在圖片上畫字
  • 製作一個驗證碼圖片
  • 結合RazorPage模板,展示驗證碼圖片

簡單介紹ImageSharp

ImageSharp是對NetCore平臺擴展的一個圖像處理方案,在寫下本文為止它最新的nuget下載量為4,034次,作者團隊最近一個月剛更新的包;沒錯這裡說最新是因為她前身和之前的版本都很受歡迎下載量也超高;她的git項目地址:https://github.com/SixLabors/ImageSharp。如果您的項目和我一樣是2.0版本(2.0以前的略過),那麼直接可以通過vs的nuget控制臺下載對應的包,註意繪圖的話需要分別下載如下兩個包:

 Install-Package SixLabors.ImageSharp -Version 1.0.0-beta0001 

 Install-Package SixLabors.ImageSharp.Drawing -Version 1.0.0-beta0001 

ImageSharp用法有朋友之前寫過,不過都主要針對於之前的版本,本章主要用到的都是最新的,有部分寫法可能不相同。

試試畫兩條線(實線和虛線)

這裡將用她來畫兩條直線並保存成圖片,主要起到一個介紹作用,先來看實線如下代碼:

var path = @"D:\F\學習\vs2017\netcore\Study.AspNetCore\WebApp02-1\wwwroot\images";
            //預設實線
            using (Image<Rgba32> image = new Image<Rgba32>(500, 500))   //畫布大小
            {
                image.Mutate(x => x.
                        BackgroundColor(Rgba32.WhiteSmoke).   //畫布背景
                            DrawLines(
                            Rgba32.HotPink, //字體顏色
                            5,   //字體大小
                            new SixLabors.Primitives.PointF[]{
                                    new Vector2(10, 10),
                                    new Vector2(200, 150),
                                    new Vector2(50, 300)
                            } //兩點一線坐標
                        )
                    );

                image.Save($"{path}/1.png"); //保存
            }

 總要步驟我都備註上文字了,這裡主要通過兩點一線來繪製圖形,Vector2對象值得註意就是C#二維坐標(x,y)對象,其實除了Vector2還有Vector3(三維坐標)等,這對於做u3d的朋友來說不會陌生,老實說這個也是我在接觸u3d時候才知道有這個類的。下麵來看效果圖:

由兩個兩點一線構造的一個角,下麵來看下虛線繪製:

//虛線
            using (Image<Rgba32> image = new Image<Rgba32>(500, 500))   //畫布大小
            {
                image.Mutate(x => x.
                        BackgroundColor(Rgba32.WhiteSmoke).   //畫布背景
                            DrawLines(
                            Pens.Dash(Rgba32.HotPink, 5),   //字體大小
                            new SixLabors.Primitives.PointF[]{
                                    new Vector2(10, 10),
                                    new Vector2(200, 150),
                                    new Vector2(50, 300)
                            } //兩點一線坐標
                        )
                    );

                image.Save($"{path}/2.png"); //保存
            }

步驟都差不多,只是調用了DrawLines的擴展方法而已,其他線條例子就不多說了各位自行實驗。

生成個縮略圖和在圖片上畫字

對於圖片類型的網站來說縮略圖是常見的,這裡用ImageSharp生成縮略圖很簡單,本實例用8.png做樣本來生成縮略圖8-1.png,直接看例子如下是netstandard 1.3+的例子:

 //縮略圖
            using (Image<Rgba32> image = Image.Load($"{path}/8.png"))
            {
                image.Mutate(x => x
                     .Resize(image.Width / 2, image.Height / 2)
                     );
                image.Save($"{path}/8-1.png");
            }

為了更好的對比縮略圖和原圖的區別這裡對接拿兩圖的屬性做對比如:

能很好的看出縮略圖文件大小和像素都減半了,實際縮略的時候不一定減半,這全由參數控制Resize(width,height);

畫字:在圖片上畫我們想要的字,其實類似於水印的一種需求,下麵是在圖片上畫字的代碼:

//畫字 
            var install_Family = new FontCollection().Install(
                System.IO.Path.Combine(Directory.GetCurrentDirectory(), "wwwroot/bak", "STKAITI.TTF")
                //@"C:\Windows\Fonts\STKAITI.TTF"   //字體文件
                );
            var font = new Font(install_Family, 50);  //字體
            using (Image<Rgba32> image = Image.Load($"{path}/8.png"))
            {
                image.Mutate(x => x
                     .DrawText(
                        "你們好,我是神牛",   //文字內容
                         font,
                         Rgba32.HotPink,
                         new Vector2(50, 150),
                         TextGraphicsOptions.Default)
                     );
                image.Save($"{path}/8-2.png");
            }

這裡用ImageSharp在圖片上畫字的時候需要註意:字體,因為windows系統自帶了字體問題這裡以STKAITI.TTF字體文件為例,它存儲於 C:\Windows\Fonts\STKAITI.TTF 目錄,當然您可以直接把它拷貝到我們項目中如下我這裡的例子一樣做法(這裡只測試了windows下可用,尚未測試linux下直接使用該字體文件是否可行);

製作一個驗證碼圖片

下麵我們將用她來畫一個驗證碼類型的圖片,通常驗證碼都有一些點和線來干擾,上面已經有畫線例子了,這裡展示怎麼畫點:

//畫點(規則的點,其他的各位自行寫演算法) 
            var dianWith = 1; //點寬度
            var xx = 300;  //圖片寬度
            var yy = 200;  //圖片高度

            var xx_space = 10;  //點與點之間x坐標間隔
            var yy_space = 5;    //y坐標間隔

            var listPath = new List<IPath>();
            for (int i = 0; i < xx / xx_space; i++)
            {
                for (int j = 0; j < yy / yy_space; j++)
                {
                    var position = new Vector2(i * xx_space, j * yy_space);
                    var linerLine = new LinearLineSegment(position, position);
                    var shapesPath = new SixLabors.Shapes.Path(linerLine);
                    listPath.Add(shapesPath);
                }
            }

            using (Image<Rgba32> image = new Image<Rgba32>(xx, yy))   //畫布大小
            {
                image.Mutate(x => x.
                        BackgroundColor(Rgba32.WhiteSmoke).   //畫布背景
                            Draw(
                            Pens.Dot(Rgba32.HotPink, dianWith),   //大小
                            new SixLabors.Shapes.PathCollection(listPath)  //坐標集合
                        )
                    );
                image.Save($"{path}/9.png"); //保存
            }

這裡直接利用IImageProcessingContext<TPixel>擴展方法Draw來繪製有規則的點,如圖所示:

比較單調,或許您們能做的更好看些;下麵來做驗證碼圖片,主要由:畫點+畫字=驗證碼圖片,這裡我封裝了一個方法直接生成驗證碼圖片:

/// <summary>
        /// 畫點+畫字=驗證碼圖片  
        /// </summary>
        /// <param name="content">驗證碼</param>
        /// <param name="outImgPath">輸出圖片路徑</param>
        /// <param name="fontFilePath">字體文件</param>
        /// <param name="x">圖片寬度</param>
        /// <param name="y">圖片高度</param>
        public void GetValidCode(
                    string content = "我是神牛",
                    string outImgPath = "D:/F/學習/vs2017/netcore/Study.AspNetCore/WebApp02-1/wwwroot/images/10.png",
                    string fontFilePath = @"D:\F\學習\vs2017\netcore\Study.AspNetCore\WebApp02-1\wwwroot\bak\STKAITI.TTF",
                    int xx = 150, int yy = 25)
        {
            var dianWith = 1; //點寬度
            var xx_space = 10;  //點與點之間x坐標間隔
            var yy_space = 5;    //y坐標間隔
            var wenZiLen = content.Length;  //文字長度
            var maxX = xx / wenZiLen; //每個文字最大x寬度
            var prevWenZiX = 0; //前面一個文字的x坐標
            var size = 16;//字體大小

            //字體
            var install_Family = new FontCollection().Install(
              fontFilePath
              //@"C:\Windows\Fonts\STKAITI.TTF"   //windows系統下字體文件
              );
            var font = new Font(install_Family, size);  //字體

            //點坐標
            var listPath = new List<IPath>();
            for (int i = 0; i < xx / xx_space; i++)
            {
                for (int j = 0; j < yy / yy_space; j++)
                {
                    var position = new Vector2(i * xx_space, j * yy_space);
                    var linerLine = new LinearLineSegment(position, position);
                    var shapesPath = new SixLabors.Shapes.Path(linerLine);
                    listPath.Add(shapesPath);
                }
            }

            //畫圖
            using (Image<Rgba32> image = new Image<Rgba32>(xx, yy))   //畫布大小
            {
                image.Mutate(x =>
                {
                    //畫點
                    var imgProc = x.BackgroundColor(Rgba32.WhiteSmoke).   //畫布背景
                              Draw(
                              Pens.Dot(Rgba32.HotPink, dianWith),   //大小
                              new SixLabors.Shapes.PathCollection(listPath)  //坐標集合
                          );

                    //逐個畫字
                    for (int i = 0; i < wenZiLen; i++)
                    {
                        //當前的要輸出的字
                        var nowWenZi = content.Substring(i, 1);

                        //文字坐標
                        var wenXY = new Vector2();
                        var maxXX = prevWenZiX + (maxX - size);
                        wenXY.X = new Random().Next(prevWenZiX, maxXX);
                        wenXY.Y = new Random().Next(0, yy - size);

                        prevWenZiX = Convert.ToInt32(Math.Floor(wenXY.X)) + size;

                        //畫字
                        imgProc.DrawText(
                           nowWenZi,   //文字內容
                           font,
                           i % 2 > 0 ? Rgba32.HotPink : Rgba32.Red,
                           wenXY,
                           TextGraphicsOptions.Default);
                    }
                });
                //保存到圖片
                image.Save(outImgPath);
            }
        }

通過簡單的調用 GetValidCode("我是神牛");return Page(); 能得到如圖驗證碼圖片的效果:

文字看起來好像在點的前面,不過沒關係只需要把畫點和畫字的先後順序修改下就行了,這裡不貼圖了;

結合RazorPage模板,展示驗證碼圖片

上面一節是生成了驗證碼圖片,當然實際場景中我們是不需要生成驗證碼物理圖片的,只需要返回一個流或base64等方式輸出到web界面上就行了,我們可以來看看 Image<TPixel> 保存時候的擴展方法:

        //
        // 摘要:
        //     Saves the image to the given stream using the currently loaded image format.
        //
        // 參數:
        //   source:
        //     The source image
        //
        //   filePath:
        //     The file path to save the image to.
        //
        // 類型參數:
        //   TPixel:
        //     The Pixel format.
        //
        // 異常:
        //   T:System.ArgumentNullException:
        //     Thrown if the stream is null.
        public static void Save<TPixel>(this Image<TPixel> source, string filePath) where TPixel : struct, IPixel<TPixel>;
        //
        // 摘要:
        //     Saves the image to the given stream using the currently loaded image format.
        //
        // 參數:
        //   source:
        //     The source image
        //
        //   filePath:
        //     The file path to save the image to.
        //
        //   encoder:
        //     The encoder to save the image with.
        //
        // 類型參數:
        //   TPixel:
        //     The Pixel format.
        //
        // 異常:
        //   T:System.ArgumentNullException:
        //     Thrown if the encoder is null.
        public static void Save<TPixel>(this Image<TPixel> source, string filePath, IImageEncoder encoder) where TPixel : struct, IPixel<TPixel>;
        //
        // 摘要:
        //     Saves the image to the given stream using the currently loaded image format.
        //
        // 參數:
        //   source:
        //     The source image
        //
        //   stream:
        //     The stream to save the image to.
        //
        //   format:
        //     The format to save the image to.
        //
        // 類型參數:
        //   TPixel:
        //     The Pixel format.
        //
        // 異常:
        //   T:System.ArgumentNullException:
        //     Thrown if the stream is null.
        public static void Save<TPixel>(this Image<TPixel> source, Stream stream, IImageFormat format) where TPixel : struct, IPixel<TPixel>;
        //
        // 摘要:
        //     Saves the image to the given stream with the bmp format.
        //
        // 參數:
        //   source:
        //     The image this method extends.
        //
        //   stream:
        //     The stream to save the image to.
        //
        // 類型參數:
        //   TPixel:
        //     The pixel format.
        //
        // 異常:
        //   T:System.ArgumentNullException:
        //     Thrown if the stream is null.
        public static void SaveAsBmp<TPixel>(this Image<TPixel> source, Stream stream) where TPixel : struct, IPixel<TPixel>;
        //
        // 摘要:
        //     Saves the image to the given stream with the bmp format.
        //
        // 參數:
        //   source:
        //     The image this method extends.
        //
        //   stream:
        //     The stream to save the image to.
        //
        //   encoder:
        //     The encoder to save the image with.
        //
        // 類型參數:
        //   TPixel:
        //     The pixel format.
        //
        // 異常:
        //   T:System.ArgumentNullException:
        //     Thrown if the stream is null.
        public static void SaveAsBmp<TPixel>(this Image<TPixel> source, Stream stream, BmpEncoder encoder) where TPixel : struct, IPixel<TPixel>;
        //
        // 摘要:
        //     Saves the image to the given stream with the gif format.
        //
        // 參數:
        //   source:
        //     The image this method extends.
        //
        //   stream:
        //     The stream to save the image to.
        //
        //   encoder:
        //     The options for the encoder.
        //
        // 類型參數:
        //   TPixel:
        //     The pixel format.
        //
        // 異常:
        //   T:System.ArgumentNullException:
        //     Thrown if the stream is null.
        public static void SaveAsGif<TPixel>(this Image<TPixel> source, Stream stream, GifEncoder encoder) where TPixel : struct, IPixel<TPixel>;
        //
        // 摘要:
        //     Saves the image to the given stream with the gif format.
        //
        // 參數:
        //   source:
        //     The image this method extends.
        //
        //   stream:
        //     The stream to save the image to.
        //
        // 類型參數:
        //   TPixel:
        //     The pixel format.
        //
        // 異常:
        //   T:System.ArgumentNullException:
        //     Thrown if the stream is null.
        public static void SaveAsGif<TPixel>(this Image<TPixel> source, Stream stream) where TPixel : struct, IPixel<TPixel>;
        //
        // 摘要:
        //     Saves the image to the given stream with the jpeg format.
        //
        // 參數:
        //   source:
        //     The image this method extends.
        //
        //   stream:
        //     The stream to save the image to.
        //
        //   encoder:
        //     The options for the encoder.
        //
        // 類型參數:
        //   TPixel:
        //     The pixel format.
        //
        // 異常:
        //   T:System.ArgumentNullException:
        //     Thrown if the stream is null.
        public static void SaveAsJpeg<TPixel>(this Image<TPixel> source, Stream stream, JpegEncoder encoder) where TPixel : struct, IPixel<TPixel>;
        //
        // 摘要:
        //     Saves the image to the given stream with the jpeg format.
        //
        // 參數:
        //   source:
        //     The image this method extends.
        //
        //   stream:
        //     The stream to save the image to.
        //
        // 類型參數:
        //   TPixel:
        //     The pixel format.
        //
        // 異常:
        //   T:System.ArgumentNullException:
        //     Thrown if the stream is null.
        public static void SaveAsJpeg<TPixel>(this Image<TPixel> source, Stream stream) where TPixel : struct, IPixel<TPixel>;
        //
        // 摘要:
        //     Saves the image to the given stream with the png format.
        //
        // 參數:
        //   source:
        //     The image this method extends.
        //
        //   stream:
        //     The stream to save the image to.
        //
        // 類型參數:
        //   TPixel:
        //     The pixel format.
        //
        // 異常:
        //   T:System.ArgumentNullException:
        //     Thrown if the stream is null.
        public static void SaveAsPng<TPixel>(this Image<TPixel> source, Stream stream) where TPixel : struct, IPixel<TPixel>;
        //
        // 摘要:
        //     Saves the image to the given stream with the png format.
        //
        // 參數:
        //   source:
        //     The image this method extends.
        //
        //   stream:
        //     The stream to save the image to.
        //
        //   encoder:
        //     The options for the encoder.
        //
        // 類型參數:
        //   TPixel:
        //     The pixel format.
        //
        // 異常:
        //   T:System.ArgumentNullException:
        //     Thrown if the stream is null.
        public static void SaveAsPng<TPixel>(this Image<TPixel> source, Stream stream, PngEncoder encoder) where TPixel : struct, IPixel<TPixel>;
        //
        // 摘要:
        //     Saves the raw image to the given bytes.
        //
        // 參數:
        //   source:
        //     The source image
        //
        //   buffer:
        //     The buffer to save the raw pixel data to.
        //
        // 類型參數:
        //   TPixel:
        //     The Pixel format.
        //
        // 異常:
        //   T:System.ArgumentNullException:
        //     Thrown if the stream is null.
        public static void SavePixelData<TPixel>(this ImageFrame<TPixel> source, byte[] buffer) where TPixel : struct, IPixel<TPixel>;
        //
        // 摘要:
        //     Saves the raw image to the given bytes.
        //
        // 參數:
        //   source:
        //     The source image
        //
        // 類型參數:
        //   TPixel:
        //     The Pixel format.
        //
        // 返回結果:
        //     A copy of the pixel data as bytes from this frame.
        //
        // 異常:
        //   T:System.ArgumentNullException:
        //     Thrown if the stream is null.
        public static byte[] SavePixelData<TPixel>(this ImageFrame<TPixel> source) where TPixel : struct, IPixel<TPixel>;
        //
        // 摘要:
        //     Saves the raw image to the given bytes.
        //
        // 參數:
        //   source:
        //     The source image
        //
        //   buffer:
        //     The buffer to save the raw pixel data to.
        //
        // 類型參數:
        //   TPixel:
        //     The Pixel format.
        //
        // 異常:
        //   T:System.ArgumentNullException:
        //     Thrown if the stream is null.
        public static void SavePixelData<TPixel>(this Image<TPixel> source, byte[] buffer) where TPixel : struct, IPixel<TPixel>;
View Code

好吧有點多,我們只需要明白她能轉base64,stream,保存為圖片等就行了;這裡我們將用到 SaveAsPng(Stream) 方法,然後獲取他的byte[],如下代碼:

/// <summary>
        /// 畫點+畫字=驗證碼byte[]
        /// </summary>
        /// <param name="content">驗證碼</param>
        /// <param name="outImgPath">輸出圖片路徑</param>
        /// <param name="fontFilePath">字體文件</param>
        /// <param name="x">圖片寬度</param>
        /// <param name="y">圖片高度</param>
        public byte[] GetValidCodeByte(
                    string content = "我是神牛",
                    string fontFilePath = @"D:\F\學習\vs2017\netcore\Study.AspNetCore\WebApp02-1\wwwroot\bak\STKAITI.TTF",
                    int xx = 150, int yy = 25)
        {
            var bb = default(byte[]);
            try
            {
                var dianWith = 1; //點寬度
                var xx_space = 10;  //點與點之間x坐標間隔
                var yy_space = 5;    //y坐標間隔
                var wenZiLen = content.Length;  //文字長度
                var maxX = xx / wenZiLen; //每個文字最大x寬度
                var prevWenZiX = 0; //前面一個文字的x坐標
                var size = 16;//字體大小

                //字體
                var install_Family = new FontCollection().Install(
                  fontFilePath
                  //@"C:\Windows\Fonts\STKAITI.TTF"   //windows系統下字體文件
                  );
                var font = new Font(install_Family, size);  //字體

                //點坐標
                var listPath = new List<IPath>();
                for (int i = 

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • foreach: continue;:退出本次迴圈 break;:退出迴圈 return;:退出迴圈 List.Foreach: return;:退出本次迴圈 小結:list.Foreach中不能退出迴圈,foreach中的return;和List.Foreach中的return;用法不同 ...
  • ActiveMQ .NET類庫 ActiveMQ是一種開源的,實現了JMS規範的,面向消息(MOM)的中間件,為應用程式提供高效的、可擴展的、穩定的和安全的企業級消息通信。 0. 準備 使用Nuget管理控制台安裝最新版 Apache.NMS.ActiveMQ PM Install Package ...
  • 回到目錄 TransactionScope是.net平臺基於的分散式事務組件,它預設為本地事務,同時當系統有需要時可以自動提升為分散式事務,而對系統的前提是要開啟MSDTC服務,必要時需要在資料庫伺服器與應用伺服器之間添加hosts的映射,這些在之前已經寫過很多文章了,在這裡不再說了。 之前對Tra ...
  • 什麼是大端和小端 Big-Endian和Little-Endian的定義如下:1) Little-Endian就是低位位元組排放在記憶體的低地址端,高位位元組排放在記憶體的高地址端。2) Big-Endian就是高位位元組排放在記憶體的低地址端,低位位元組排放在記憶體的高地址端。舉一個例子,比如數字0x12 34 ...
  • lock 關鍵字將語句塊標記為臨界區,方法是獲取給定對象的互斥鎖,執行語句,然後釋放該鎖。 lock語句根本使用的就是Monitor.Enter和Monitor.Exit,也就是說lock(this)時執行Monitor.Enter(this),大括弧結束時執行Monitor.Exit(this). ...
  • 閱讀目錄 背景 代碼描述 越分析越黑暗 結語 一、背景 這個標題起的有點標題黨的嫌疑[捂臉],這個事情的原委是這樣的,有個Web API的站點在本地使用Release模式Run的時候出現問題,但是使用Debug模式則不會。通過打日誌定位到問題在如下的這個代碼這裡: 理論上,會有一次請求進入到2中,但 ...
  • 一、Quartz.NET介紹 Quartz.NET是一個強大、開源、輕量的作業調度框架,是 OpenSymphony 的 Quartz API 的.NET移植,用C#改寫,可用於winform和asp.net應用中。它靈活而不複雜。你能夠用它來為執行一個作業而創建簡單的或複雜的作業調度。它有很多特征 ...
  • Parallel類 在System.Threading.Tasks 命名空間下 下麵有幾個方法,這裡講一下Invoke的用法 下麵我們定義幾個方法方便測試 先自定義Response 防止並行的時候占用導致結果變化 HttpResponse MyResponse = System.Web.HttpCo ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...