最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C#利用Spire.Pdf包實(shí)現(xiàn)為PDF添加數(shù)字簽名

 更新時(shí)間:2022年08月31日 16:45:13   作者:旅途。  
Spire.PDF for .NET 是一款專業(yè)的基于.NET平臺(tái)的PDF文檔控制組件。它能夠讓開(kāi)發(fā)人員在不使用Adobe Acrobat和其他外部控件的情況下,運(yùn)用.NET 應(yīng)用程序創(chuàng)建,閱讀,編寫(xiě)和操縱PDF 文檔。本文將利用其實(shí)現(xiàn)添加數(shù)字簽名,需要的可以參考一下

背景

  • 對(duì)PDF文檔進(jìn)行數(shù)字簽名的需求
  • 對(duì)PDF文檔添加水印的需求
  • 網(wǎng)上資料版本不一或不全

本文章提到的Spire.Pdf均是使用的Spire.Pdf for .NET,除此之前還有其他語(yǔ)言的版本,如Spire.Pdf for JAVA;
Spire.Pdf主要用于操作PDF,另外還有Spire.Excel、Spire.Doc等
主要介紹了在C#中使用Spire.Pdf組件包對(duì)PDF文檔進(jìn)行數(shù)字簽名、添加水印功能,旨在引導(dǎo)大家快速、輕松的對(duì)PDF文檔進(jìn)行數(shù)字簽名和添加水印功能;

簡(jiǎn)介

Spire.PDF for .NET 是一款專業(yè)的基于.NET平臺(tái)的PDF文檔控制組件。它能夠讓開(kāi)發(fā)人員在不使用Adobe Acrobat和其他外部控件的情況下,運(yùn)用.NET 應(yīng)用程序創(chuàng)建,閱讀,編寫(xiě)和操縱PDF 文檔。Spire.PDF for .NET 功能豐富,除了基本的功能比如:繪制多種圖形,圖片,創(chuàng)建窗體字段,插入頁(yè)眉頁(yè)腳,輸入數(shù)據(jù)表,自動(dòng)對(duì)大型表格進(jìn)行分頁(yè)外,Spire.PDF for .NET還支持PDF數(shù)字簽名,將HTML轉(zhuǎn)換成PDF格式,提取PDF文檔中的文本信息和圖片等,目前Spire.PDF for .NET共有兩個(gè)版本,一個(gè)是免費(fèi)版本一個(gè)是付費(fèi)版本,免費(fèi)版本如果只是處理簡(jiǎn)單的pdf是沒(méi)問(wèn)題的,但是如果涉及到輸出為pdf則會(huì)只顯示前10頁(yè),第十一頁(yè)則是預(yù)定的購(gòu)買(mǎi)頁(yè)介紹,我這里主要是對(duì)PDF文檔的數(shù)字簽名和水印,所以不涉及輸出pdf;

依賴

本文示例代碼依賴于Spire.Pdf,可以在項(xiàng)目中使用NuGet程序包引入。

源碼

核心代碼

public class DigitalSignature
    {
        /// <summary>
        /// 頁(yè)頂部紅色警告字樣覆蓋白色圖片Base64.
        /// </summary>
        private const string WatermarkCoverBase64 = "/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAMCAgMCAgMDAwMEAwMEBQgFBQQEBQoHBwYIDAoMDAsKCwsNDhIQDQ4RDgsLEBYQERMUFRUVDA8XGBYUGBIUFRT/2wBDAQMEBAUEBQkFBQkUDQsNFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBT/wAARCABHAycDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD9U6KKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooA//Z";

        /// <summary>
        /// 構(gòu)造函數(shù).
        /// </summary>
        /// <param name="waitSignFile">待簽名文件.</param>
        /// <param name="imageSign">簽名圖片.</param>
        /// <param name="pfx">簽名證書(shū).</param>
        /// <param name="pfxPwd">簽名證書(shū)密碼.</param>
        public DigitalSignature(byte[] waitSignFile, byte[] imageSign, byte[] pfx, string pfxPwd)
        {
            this.WaitSignFile = waitSignFile;
            this.ImageSign = imageSign;
            this.Pfx = pfx;
            this.PfxPwd = pfxPwd;
        }

        /// <summary>
        /// 構(gòu)造函數(shù).
        /// </summary>
        /// <param name="waitSignFile">待簽名文件.</param>
        /// <param name="charactersSign">簽名文字.</param>
        /// <param name="signRightLeftWidth">簽名右向左寬度.</param>
        /// <param name="signBottomUpHeight">簽名低向上高度.</param>
        /// <param name="pfx">簽名證書(shū).</param>
        /// <param name="pfxPwd">簽名證書(shū)密碼.</param>
        public DigitalSignature(byte[] waitSignFile, string charactersSign, float signRightLeftWidth, float signBottomUpHeight, byte[] pfx, string pfxPwd)
        {
            this.WaitSignFile = waitSignFile;
            this.CharactersSign = charactersSign;
            this.SignRightLeftWidth = signRightLeftWidth;
            this.SignBottomUpHeight = signBottomUpHeight;
            this.Pfx = pfx;
            this.PfxPwd = pfxPwd;
        }

        /// <summary>
        /// 構(gòu)造函數(shù).
        /// </summary>
        /// <param name="waitSignFile">待簽名文件.</param>
        /// <param name="imageSign">簽名圖片.</param>
        /// <param name="charactersSign">簽名文字.</param>
        /// <param name="pfx">簽名證書(shū).</param>
        /// <param name="pfxPwd">簽名證書(shū)密碼.</param>
        public DigitalSignature(byte[] waitSignFile, byte[] imageSign, string charactersSign, byte[] pfx, string pfxPwd)
        {
            this.WaitSignFile = waitSignFile;
            this.ImageSign = imageSign;
            this.CharactersSign = charactersSign;
            this.Pfx = pfx;
            this.PfxPwd = pfxPwd;
        }

        /// <summary>
        /// Gets or sets 待簽名文件.
        /// </summary>
        public byte[] WaitSignFile { get; set; }

        /// <summary>
        /// Gets or sets 圖簽名.
        /// </summary>
        public byte[] ImageSign { get; set; }

        /// <summary>
        /// Gets or sets 文字簽名.
        /// </summary>
        public string CharactersSign { get; set; }

        /// <summary>
        /// Gets or sets 簽名右向左的寬度.
        /// </summary>
        public float? SignRightLeftWidth { get; set; }

        /// <summary>
        /// Gets or sets 簽名頂向上高度.
        /// </summary>
        public float? SignBottomUpHeight { get; set; }

        /// <summary>
        /// Gets or sets 簽名索引頁(yè)面(不指定默認(rèn)所有頁(yè)進(jìn)行簽名).
        /// </summary>
        public int? SignIndexPages { get; set; }

        /// <summary>
        /// Gets or sets Pfx證書(shū).
        /// </summary>
        public byte[] Pfx { get; set; }

        /// <summary>
        /// Gets or sets Pfx證書(shū)密碼.
        /// </summary>
        public string PfxPwd { get; set; }

        public Stream Signature()
        {
            ///加載PDF文檔
            PdfDocument pdf = new PdfDocument();
            pdf.LoadFromBytes(this.WaitSignFile);

            if (pdf?.Pages?.Count <= 0)
            {
                throw new Exception("文件有誤");
            }

            X509Certificate2 x509 = new X509Certificate2(this.Pfx, this.PfxPwd);
            PdfOrdinarySignatureMaker signatureMaker = new PdfOrdinarySignatureMaker(pdf, x509);

            var appearance = new PdfCustomSignatureAppearance(this.CharactersSign, this.ImageSign, this.SignRightLeftWidth, this.SignBottomUpHeight);
            IPdfSignatureAppearance signatureAppearance = appearance;

            // 繪畫(huà)白底圖片
            PdfRubberStampAnnotation logoStamp = new PdfRubberStampAnnotation(new RectangleF(new PointF(0, 0), new SizeF(350, 22)));
            PdfAppearance logoApprearance = new PdfAppearance(logoStamp);
            //var logoPath = AppDomain.CurrentDomain.BaseDirectory + "\\white.jpg";
            byte[] byt = Convert.FromBase64String(WatermarkCoverBase64);
            Stream streamByLogo = new MemoryStream(byt);
            PdfImage image = PdfImage.FromStream(streamByLogo);
            PdfTemplate template = new PdfTemplate(350, 22);
            template.Graphics.DrawImage(image, 0, 0);
            logoApprearance.Normal = template;
            logoStamp.Appearance = logoApprearance;

            if (this.SignIndexPages.HasValue)
            {
                if (this.SignIndexPages.Value < 0 || this.SignIndexPages.Value > pdf?.Pages?.Count)
                {
                    throw new Exception("簽名索引頁(yè)有誤");
                }

                var page = pdf.Pages[this.SignIndexPages.Value];

                // 添加白底圖片覆蓋頁(yè)面頂部印記
                page.AnnotationsWidget.Add(logoStamp);

                // 在頁(yè)面中的指定位置添加可視化簽名
                signatureMaker.MakeSignature("signName_", page, page.ActualSize.Width - appearance.SignRightLeftWidth, page.ActualSize.Height - appearance.SignBottomUpHeight, appearance.SignRightLeftWidth, appearance.SignBottomUpHeight, signatureAppearance);
            }
            else
            {
                foreach (PdfPageBase page in pdf.Pages)
                {
                    // 添加白底圖片覆蓋頁(yè)面頂部印記
                    page.AnnotationsWidget.Add(logoStamp);

                    // 在頁(yè)面中的指定位置添加可視化簽名
                    signatureMaker.MakeSignature("signName_", page, page.ActualSize.Width - appearance.SignRightLeftWidth, page.ActualSize.Height - appearance.SignBottomUpHeight, appearance.SignRightLeftWidth, appearance.SignBottomUpHeight, signatureAppearance);
                }
            }

            MemoryStream stream = new MemoryStream();
            pdf.SaveToStream(stream, FileFormat.PDF);
            pdf.Close();
            return stream;
        }

        /// <summary>
        /// 使用第三方插件 =》 去除  Evaluation Warning : The document was created with Spire.PDF for .NET.
        /// </summary>
        /// <param name="sourcePdfs">原文件地址</param>
        //private static MemoryStream ClearPdfFilesFirstPage(MemoryStream sourcePdf)
        //{
        //    iTextSharp.text.pdf.PdfReader reader = null;
        //    iTextSharp.text.Document document = new iTextSharp.text.Document();
        //    iTextSharp.text.pdf.PdfImportedPage page = null;
        //    iTextSharp.text.pdf.PdfCopy pdfCpy = null;
        //    int n = 0;
        //    reader = new iTextSharp.text.pdf.PdfReader(sourcePdf);
        //    reader.ConsolidateNamedDestinations();
        //    n = reader.NumberOfPages;
        //    document = new iTextSharp.text.Document(reader.GetPageSizeWithRotation(1));
        //    MemoryStream memoryStream = new MemoryStream();
        //    pdfCpy = new iTextSharp.text.pdf.PdfCopy(document, memoryStream);
        //    document.Open();
        //    for (int j = 2; j <= n; j++)
        //    {
        //        page = pdfCpy.GetImportedPage(reader, j);
        //        pdfCpy.AddPage(page);

        //    }
        //    reader.Close();
        //    document.Close();
        //    return memoryStream;
        //}
    }


    public class PdfCustomSignatureAppearance : IPdfSignatureAppearance
    {
        public PdfCustomSignatureAppearance(string charactersSign, byte[] sign, float? signRightLeftWidth, float? signBottomUpHeight)
        {
            this.CharactersSign = charactersSign;

            if (sign != null && sign.Length > 0)
            {
                this.Sign = sign;
                MemoryStream ms = new MemoryStream(sign);
                var image = System.Drawing.Image.FromStream(ms);
                if (!signRightLeftWidth.HasValue)
                {
                    signRightLeftWidth = image.Width;
                }

                if (!signBottomUpHeight.HasValue)
                {
                    signBottomUpHeight = image.Height;
                }
            }

            this.SignRightLeftWidth = signRightLeftWidth.Value;
            this.SignBottomUpHeight = signBottomUpHeight.Value;
        }

        /// <summary>
        /// Gets or sets 簽名.
        /// </summary>
        public byte[] Sign { get; set; }

        /// <summary>
        /// Gets or sets 簽名右向左的寬度.
        /// </summary>
        public float SignRightLeftWidth { get; set; }

        /// <summary>
        /// Gets or sets 簽名頂向上高度.
        /// </summary>
        public float SignBottomUpHeight { get; set; }

        /// <summary>
        /// Gets or sets 文字簽名.
        /// </summary>
        public string CharactersSign { get; set; }

        public void Generate(PdfCanvas g)
        {
            if (!string.IsNullOrWhiteSpace(CharactersSign))
            {
                float fontSize = 15;
                var font = new System.Drawing.Font("Arial", fontSize);
                PdfTrueTypeFont fontByPdf = new PdfTrueTypeFont(font, true);
                g.DrawString(CharactersSign, fontByPdf, PdfBrushes.Black, new PointF(0, 0));
            }

            if (this.Sign != null && this.Sign.Length > 0)
            {
                Stream stream = new MemoryStream(this.Sign);
                g.DrawImage(Spire.Pdf.Graphics.PdfImage.FromStream(stream), new PointF(20, 20));
            }
        }
    }

調(diào)用實(shí)現(xiàn)

static void Main(string[] args)
        {

            /*
                前言:最近有個(gè)需求是需要對(duì)文檔進(jìn)行數(shù)字簽名;
                描述:本示例基于Spire.Pdf組件對(duì)PDF進(jìn)行數(shù)字簽名,演示了
                    簽名證書(shū)使用項(xiàng)目
            CreateSelfSignedCertificateByBouncyCastle(https://github.com/daileass/CreateSelfSignedCertificateByBouncyCastle.git)
                    生成的自簽名證書(shū)pfx,解決了數(shù)字簽名后文檔頭部有警告

            */

            var fileCert = System.Environment.CurrentDirectory + "\\Cert\\";
            var file = System.Environment.CurrentDirectory + "\\File\\";
            var filePath = file + "dome.pdf";
            var newFilePath = file + $"dome_{DateTime.Now.ToString("yyyyMMddHHmmss")}.pdf";
            var pfxFilePath = fileCert + "edd9386229324d969692dcabf97ac095dpps.fun.pfx";
            var pfxFilePwd = "ABCD123456";
            var signFilePath = file + "sign.png";

            // 數(shù)字簽名
            var digitalSignature = new DigitalSignature(
                File2Bytes(filePath),
                File2Bytes(signFilePath),
                "Sign Here:",
                File2Bytes(pfxFilePath),
                pfxFilePwd
                );
            var stream = digitalSignature.Signature();

            // 保存簽名后的文件
            using (var fileStream = File.Create(newFilePath))
            {
                stream.Seek(0, SeekOrigin.Begin);
                stream.CopyTo(fileStream);
            }

            Console.WriteLine("OK");
            Console.ReadLine();
        }

        /// <summary>
        /// 將文件轉(zhuǎn)換為byte數(shù)組
        /// </summary>
        /// <param name="path">文件地址</param>
        /// <returns>轉(zhuǎn)換后的byte數(shù)組</returns>
        public static byte[] File2Bytes(string path)
        {
            if (!System.IO.File.Exists(path))
            {
                return new byte[0];
            }

            FileInfo fi = new FileInfo(path);
            byte[] buff = new byte[fi.Length];

            FileStream fs = fi.OpenRead();
            fs.Read(buff, 0, Convert.ToInt32(fs.Length));
            fs.Close();

            return buff;
        }

源碼下載:https://github.com/daileass/PDFDigitalSignatureBySelfSignedCertificate

到此這篇關(guān)于C#利用Spire.Pdf包實(shí)現(xiàn)為PDF添加數(shù)字簽名的文章就介紹到這了,更多相關(guān)C# PDF添加數(shù)字簽名內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • c#基礎(chǔ)系列之ref和out的深入理解

    c#基礎(chǔ)系列之ref和out的深入理解

    有過(guò)C#基礎(chǔ)知識(shí)的都應(yīng)該清楚Ref和Out的使用方法,所以下面這篇文章主要給大家介紹了關(guān)于c#基礎(chǔ)系列之ref和out的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2018-09-09
  • 用Linq從一個(gè)集合選取幾列得到一個(gè)新的集合(可改列名)

    用Linq從一個(gè)集合選取幾列得到一個(gè)新的集合(可改列名)

    這篇文章主要介紹了用Linq從一個(gè)集合選取幾列得到一個(gè)新的集合(可改列名),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-12-12
  • C#關(guān)鍵字之覆寫(xiě)overwrite介紹

    C#關(guān)鍵字之覆寫(xiě)overwrite介紹

    這篇文章介紹了C#關(guān)鍵字之覆寫(xiě)overwrite,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-04-04
  • 淺析C#中靜態(tài)方法和非靜態(tài)方法的區(qū)別

    淺析C#中靜態(tài)方法和非靜態(tài)方法的區(qū)別

    C#靜態(tài)方法與非靜態(tài)方法的區(qū)別不僅僅是概念上的,那么他們有什么具體的區(qū)別呢?讓我們通過(guò)本文向大家介紹下C#中靜態(tài)方法和非靜態(tài)方法的區(qū)別,一起看看吧
    2017-09-09
  • 詳解C#如何實(shí)現(xiàn)隱式類型轉(zhuǎn)換

    詳解C#如何實(shí)現(xiàn)隱式類型轉(zhuǎn)換

    Result?類型是許多編程語(yǔ)言中處理錯(cuò)誤的常用方式,包括?C#?的?dotNext?庫(kù)。在本文中,我們將通過(guò)例子回顧?C#?中?using?語(yǔ)句和隱式類型轉(zhuǎn)換的使用,感興趣的可以了解一下
    2023-01-01
  • Unity實(shí)現(xiàn)局域網(wǎng)聊天室功能

    Unity實(shí)現(xiàn)局域網(wǎng)聊天室功能

    這篇文章主要為大家詳細(xì)介紹了Unity實(shí)現(xiàn)局域網(wǎng)聊天室功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-10-10
  • C#實(shí)現(xiàn)搶紅包算法的示例代碼

    C#實(shí)現(xiàn)搶紅包算法的示例代碼

    很多商家都會(huì)使用紅包進(jìn)行促銷(xiāo),那么你知道紅包算法是怎么實(shí)現(xiàn)的嗎,本文主要介紹了C#實(shí)現(xiàn)搶紅包算法,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • c#多線程網(wǎng)絡(luò)聊天程序代碼分享(服務(wù)器端和客戶端)

    c#多線程網(wǎng)絡(luò)聊天程序代碼分享(服務(wù)器端和客戶端)

    本程序使用VS2005 制作,程序分為三塊,XuLIeHua類庫(kù)下有我寫(xiě)的把結(jié)構(gòu)序列化的類,還有就是服務(wù)器端和客戶端
    2013-12-12
  • C# Winform TextBox控件多行輸入方式

    C# Winform TextBox控件多行輸入方式

    這篇文章主要介紹了C# Winform TextBox控件多行輸入方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • 使用C#校驗(yàn)畫(huà)布簽名圖片是否為空白

    使用C#校驗(yàn)畫(huà)布簽名圖片是否為空白

    這篇文章主要為大家詳細(xì)介紹了如何使用C#校驗(yàn)畫(huà)布簽名圖片是否為空白,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-11-11

最新評(píng)論

桑植县| 贵港市| 揭阳市| 林口县| 荣昌县| 贡嘎县| 通海县| 基隆市| 涟水县| 清水河县| 沧州市| 邯郸县| 玛多县| 岳普湖县| 莱芜市| 南澳县| 舒城县| 晋中市| 法库县| 民和| 贡山| 钟祥市| 舞钢市| 南安市| 龙井市| 衡水市| 泰来县| 五指山市| 房产| 浠水县| 澜沧| 同江市| 淮滨县| 河曲县| 青神县| 平潭县| 五莲县| 哈密市| 会昌县| 木兰县| 卓资县|