C#文件安全管理解析

来源:http://www.cnblogs.com/pengze0902/archive/2016/12/15/6164531.html
-Advertisement-
Play Games

在實際的項目開發中,我們經常需要使用到文件的I/O操作,主要包含對文件的增改刪查等操作,這些基本的操作我們都是很熟悉,但是較少的人去考慮文件的安全和操作的管理等方面,例如文件的訪問許可權管理,文件數據的徹底刪除和數據的恢復等等,這一系列的操作需要我們對.NET的相關知識有一個深刻的學習。 在本文章主要 ...


    在實際的項目開發中,我們經常需要使用到文件的I/O操作,主要包含對文件的增改刪查等操作,這些基本的操作我們都是很熟悉,但是較少的人去考慮文件的安全和操作的管理等方面,例如文件的訪問許可權管理,文件數據的徹底刪除和數據的恢復等等,這一系列的操作需要我們對.NET的相關知識有一個深刻的學習。

   在本文章主要介紹文件和目錄的一些基本操作,以及文件目錄的許可權和安全設置的相關內容。

一.DotNet文件目錄常用操作:

    提到文件的I/O操作,這個對於每一個開發者來說都不是陌生的事,因為這些操作是我們在項目開發過程中經常使用到的一些操作。那麼在.NET中操作文件的類在System.IO命名空間下,一下介紹一下常見的I/O操作類:

        DiveInfo:提供了對邏輯磁碟的基本信息訪問的途徑。(只能查看信息,不能做任何修改。)

        System.Environment:用來枚舉驅動器。(不能獲取驅動器的屬性)

        System.Management:.NET針對WMI調用。

        Directory和DircetoryInfo:用於操作目錄。(前者為靜態類,後者則須在實例化後調用,功能上相同)

        File和FileInfo:用於操作文件。(前者為靜態類,後者須實例化後調用,功能上相同)

    以上介紹了一些文件的基本操作類,本次主要講解目錄和文件操作,一下給出文件和目錄操作的一些基本方法:

   1.文件常規操作:

      (1).文件讀寫操作:
        /// <summary>
        /// 寫文件
        /// </summary>
        /// <param name="fileName">文件名</param>
        /// <param name="content">文件內容</param>
        /// <param name="encoding">指定文件編碼</param>
        protected void Write_Txt(string fileName, string content, string encoding)
        {
            if (string.IsNullOrEmpty(fileName))
            {
                throw new ArgumentNullException(fileName);
            }
            if (string.IsNullOrEmpty(content))
            {
                throw new ArgumentNullException(content);
            }
            if (string.IsNullOrEmpty(encoding))
            {
                throw new ArgumentNullException(encoding);
            }
            var code = Encoding.GetEncoding(encoding);
            var htmlfilename = HttpContext.Current.Server.MapPath("Precious\\" + fileName + ".txt");
            var str = content;
            var sw = StreamWriter.Null;
            try
            {
                using (sw = new StreamWriter(htmlfilename, false, code))
                {
                    sw.Write(str);
                    sw.Flush();
                }
            }
            catch (IOException ioex)
            {
                throw new IOException(ioex.Message);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
            finally
            {
                sw.Close();
            }
        }

        /// <summary>
        /// 讀文件
        /// </summary>
        /// <param name="filename">文件路徑</param>
        /// <param name="encoding">文件編碼</param>
        /// <returns></returns>
        protected string Read_Txt(string filename, string encoding)
        {
            if (string.IsNullOrEmpty(filename))
            {
                throw new ArgumentNullException(filename);
            }
            if (string.IsNullOrEmpty(encoding))
            {
                throw new ArgumentNullException(encoding);
            }
            var code = Encoding.GetEncoding(encoding);
            var temp = HttpContext.Current.Server.MapPath("Precious\\" + filename + ".txt");
            var str = string.Empty;
            if (!System.IO.File.Exists(temp)) return str;
            var sr = StreamReader.Null;
            try
            {
                using (sr = new StreamReader(temp, code))
                {
                    str = sr.ReadToEnd();
                }
            }
            catch (IOException ioex)
            {
                throw new IOException(ioex.Message);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
            finally
            {
                sr.Close();
            }
            return str;
        }
    (2).文件附加操作:
        /// <summary>
        /// 拷貝文件
        /// </summary>
        /// <param name="orignFile">原始文件</param>
        /// <param name="newFile">新文件路徑</param>
        public static void FileCoppy(string orignFile, string newFile)
        {
            if (string.IsNullOrEmpty(orignFile))
            {
                throw new ArgumentException(orignFile);
            }
            if (string.IsNullOrEmpty(newFile))
            {
                throw new ArgumentException(newFile);
            }
            System.IO.File.Copy(orignFile, newFile, true);
        }

        /// <summary>
        /// 刪除文件
        /// </summary>
        /// <param name="path">路徑</param>
        public static void FileDel(string path)
        {
            if (string.IsNullOrEmpty(path))
            {
                throw new ArgumentException(path);
            }
            System.IO.File.Delete(path);
        }

        /// <summary>
        /// 移動文件
        /// </summary>
        /// <param name="orignFile">原始路徑</param>
        /// <param name="newFile">新路徑</param>
        public static void FileMove(string orignFile, string newFile)
        {
            if (string.IsNullOrEmpty(orignFile))
            {
                throw new ArgumentException(orignFile);
            }
            if (string.IsNullOrEmpty(newFile))
            {
                throw new ArgumentException(newFile);
            }
            System.IO.File.Move(orignFile, newFile);
        }

    2.目錄常規操作:

        /// <summary>
        /// 在當前目錄下創建目錄
        /// </summary>
        /// <param name="orignFolder">當前目錄</param>
        /// <param name="newFloder">新目錄</param>
        public static void FolderCreate(string orignFolder, string newFloder)
        {
            if (string.IsNullOrEmpty(orignFolder))
            {
                throw new ArgumentException(orignFolder);
            }
            if (string.IsNullOrEmpty(newFloder))
            {
                throw new ArgumentException(newFloder);
            }
            Directory.SetCurrentDirectory(orignFolder);
            Directory.CreateDirectory(newFloder);
        }

        /// <summary>
        /// 創建文件夾
        /// </summary>
        /// <param name="path"></param>
        public static void FolderCreate(string path)
        {
            if (string.IsNullOrEmpty(path))
            {
                throw new ArgumentException(path);
            }
            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }               
        }

        public static void FileCreate(string path)
        {
            if (string.IsNullOrEmpty(path))
            {
                throw new ArgumentException(path);
            }
            var createFile = new FileInfo(path);
            if (createFile.Exists) return;
            var fs = createFile.Create();
            fs.Close();
            fs.Dispose();
        }

        /// <summary>
        /// 遞歸刪除文件夾目錄及文件
        /// </summary>
        /// <param name="dir"></param>  
        /// <returns></returns>
        public static void DeleteFolder(string dir)
        {
            if (string.IsNullOrEmpty(dir))
            {
                throw new ArgumentException(dir);
            }
            if (!Directory.Exists(dir)) return;
            foreach (var d in Directory.GetFileSystemEntries(dir))
            {
                if (System.IO.File.Exists(d))
                {
                    //直接刪除其中的文件 
                    System.IO.File.Delete(d); 
                }
                else
                {
                    //遞歸刪除子文件夾 
                    DeleteFolder(d);
                }                    
            }
            //刪除已空文件夾        
            Directory.Delete(dir, true);          
        }

        /// <summary>
        /// 指定文件夾下麵的所有內容copy到目標文件夾下麵
        /// </summary>
        /// <param name="srcPath">原始路徑</param>
        /// <param name="aimPath">目標文件夾</param>
        public static void CopyDir(string srcPath, string aimPath)
        {
            if (string.IsNullOrEmpty(srcPath))
            {
                throw new ArgumentNullException(srcPath);
            }
            if (string.IsNullOrEmpty(aimPath))
            {
                throw new ArgumentNullException(aimPath);
            }
            try
            {
                if (aimPath[aimPath.Length - 1] != Path.DirectorySeparatorChar)
                {
                    aimPath += Path.DirectorySeparatorChar;
                }
                if (!Directory.Exists(aimPath))
                {
                    Directory.CreateDirectory(aimPath);
                }
                var fileList = Directory.GetFileSystemEntries(srcPath);
                foreach (var file in fileList)
                {
                    if (Directory.Exists(file))
                    {
                        CopyDir(file, aimPath + Path.GetFileName(file));
                    }
                    else
                    {
                        System.IO.File.Copy(file, aimPath + Path.GetFileName(file), true);
                    }
                }
            }
            catch (IOException ioex)
            {
                throw new IOException(ioex.Message);
            }
            catch (Exception ee)
            {
                throw new Exception(ee.ToString());
            }
        }

        /// <summary>
        /// 獲取指定文件夾下所有子目錄及文件
        /// </summary>
        /// <param name="path">詳細路徑</param>
        public static string GetFoldAll(string path)
        {
            if (string.IsNullOrEmpty(path))
            {
                throw new ArgumentNullException(path);
            }
            var str =string.Empty;
            var thisOne = new DirectoryInfo(path);
            str = ListTreeShow(thisOne, 0, str);
            return str;

        }

        /// <summary>
        /// 獲取指定文件夾下所有子目錄及文件函數
        /// </summary>
        /// <param name="theDir">指定目錄</param>
        /// <param name="nLevel">預設起始值,調用時,一般為0</param>
        /// <param name="rn">用於迭加的傳入值,一般為空</param>
        /// <returns></returns>
        public static string ListTreeShow(DirectoryInfo theDir, int nLevel, string rn)
        {
            if (theDir == null)
            {
                throw new ArgumentNullException("theDir");
            }
            //獲得目錄
            DirectoryInfo[] subDirectories = theDir.GetDirectories();
            foreach (DirectoryInfo dirinfo in subDirectories)
            {

                if (nLevel == 0)
                {
                    rn += "";
                }
                else
                {
                    var s =string.Empty;
                    for (int i = 1; i <= nLevel; i++)
                    {
                        s += "│&nbsp;";
                    }
                    rn += s + "";
                }
                rn += "<b>" + dirinfo.Name + "</b><br />";
                //目錄下的文件
                var fileInfo = dirinfo.GetFiles();   
                foreach (FileInfo fInfo in fileInfo)
                {
                    if (nLevel == 0)
                    {
                        rn += "│&nbsp;├";
                    }
                    else
                    {
                        var f = string.Empty;
                        for (int i = 1; i <= nLevel; i++)
                        {
                            f += "│&nbsp;";
                        }
                        rn += f + "│&nbsp;├";
                    }
                    rn += fInfo.Name.ToString() + " <br />";
                }
                rn = ListTreeShow(dirinfo, nLevel + 1, rn);


            }
            return rn;
        }

        /// <summary>
        /// 獲取指定文件夾下所有子目錄及文件(下拉框形)
        /// </summary>
        /// <param name="path">詳細路徑</param>
        ///<param name="dropName">下拉列表名稱</param>
        ///<param name="tplPath">預設選擇模板名稱</param>
        public static string GetFoldAll(string path, string dropName, string tplPath)
        {
            if (string.IsNullOrEmpty(path))
            {
                throw new ArgumentNullException(path);
            }
            if (string.IsNullOrEmpty(tplPath))
            {
                throw new ArgumentNullException(tplPath);
            }
            var strDrop = "<select name=\"" + dropName + "\" id=\"" + dropName + "\"><option value=\"\">--請選擇詳細模板--</option>";
            var str =string.Empty;
            DirectoryInfo thisOne = new DirectoryInfo(path);
            str = ListTreeShow(thisOne, 0, str, tplPath);
            return strDrop + str + "</select>";

        }

        /// <summary>
        /// 獲取指定文件夾下所有子目錄及文件函數
        /// </summary>
        /// <param name="theDir">指定目錄</param>
        /// <param name="nLevel">預設起始值,調用時,一般為0</param>
        /// <param name="rn">用於迭加的傳入值,一般為空</param>
        /// <param name="tplPath">預設選擇模板名稱</param>
        /// <returns></returns>
        public static string ListTreeShow(DirectoryInfo theDir, int nLevel, string rn, string tplPath)
        {
            if (theDir == null)
            {
                throw new ArgumentNullException("theDir");
            }
            //獲得目錄
            DirectoryInfo[] subDirectories = theDir.GetDirectories();
            foreach (DirectoryInfo dirinfo in subDirectories)
            {
                rn += "<option value=\"" + dirinfo.Name + "\"";
                if (string.Equals(tplPath, dirinfo.Name, StringComparison.CurrentCultureIgnoreCase))
                {
                    rn += " selected ";
                }
                rn += ">";

                if (nLevel == 0)
                {
                    rn += "";
                }
                else
                {
                    string s = string.Empty;
                    for (int i = 1; i <= nLevel; i++)
                    {
                        s += "│&nbsp;";
                    }
                    rn += s + "";
                }
                rn += "" + dirinfo.Name + "</option>";
                //目錄下的文件
                FileInfo[] fileInfo = dirinfo.GetFiles();  
                foreach (FileInfo fInfo in fileInfo)
                {
                    rn += "<option value=\"" + dirinfo.Name + "/" + fInfo.Name + "\"";
                    if (string.Equals(tplPath, fInfo.Name, StringComparison.CurrentCultureIgnoreCase))
                    {
                        rn += " selected ";
                    }
                    rn += ">";

                    if (nLevel == 0)
                    {
                        rn += "│&nbsp;├";
                    }
                    else
                    {
                        string f = string.Empty;
                        for (int i = 1; i <= nLevel; i++)
                        {
                            f += "│&nbsp;";
                        }
                        rn += f + "│&nbsp;├";
                    }
                    rn += fInfo.Name + "</option>";
                }
                rn = ListTreeShow(dirinfo, nLevel + 1, rn, tplPath);
            }
            return rn;
        }

        /// <summary>
        /// 獲取文件夾大小
        /// </summary>
        /// <param name="dirPath">文件夾路徑</param>
        /// <returns></returns>
        public static long GetDirectoryLength(string dirPath)
        {
            if (string.IsNullOrEmpty(dirPath))
            {
                throw new ArgumentNullException(dirPath);
            }
            if (!Directory.Exists(dirPath))
            {
                return 0;
            }              
            long len = 0;
            DirectoryInfo di = new DirectoryInfo(dirPath);
            foreach (FileInfo fi in di.GetFiles())
            {
                len += fi.Length;
            }
            DirectoryInfo[] dis = di.GetDirectories();
            if (dis.Length > 0)
            {
                for (int i = 0; i < dis.Length; i++)
                {
                    len += GetDirectoryLength(dis[i].FullName);
                }
            }
            return len;
        }

        /// <summary>
        /// 獲取指定文件詳細屬性
        /// </summary>
        /// <param name="filePath">文件詳細路徑</param>
        /// <returns></returns>
        public static string GetFileAttibe(string filePath)
        {
            if (string.IsNullOrEmpty(filePath))
            {
                throw new ArgumentNullException(filePath);
            }
            var str = string.Empty;
            FileInfo objFi = new FileInfo(filePath);
            str += "詳細路徑:" + objFi.FullName + "<br>文件名稱:" + objFi.Name + "<br>文件長度:" + objFi.Length + "位元組<br>創建時間" + objFi.CreationTime.ToString() + "<br>最後訪問時間:" + objFi.LastAccessTime.ToString() + "<br>修改時間:" + objFi.LastWriteTime.ToString() + "<br>所在目錄:" + objFi.DirectoryName + "<br>擴展名:" + objFi.Extension;
            return str;
        }

 

二.DotNet文件目錄訪問管理:

    1.文件目錄許可權概述:

       提到許可權這個概念,這對於每一個開發者都是再熟悉不過的,因為我們在開發項目時,都會考慮用戶許可權管理等等,但是文件的許可權操作呢?這裡我們就簡單的介紹一下.NET中對文件訪問許可權的訪問和設置。文件許可權中的訪問控制列表: 自由訪問控制列表(DACL):Microsoft Windows NT和更高版本用於保護資源的機制;系統訪問控制列表(SACL):一種控制與資源關聯的審核消息的機制。System.Security.AccessControl命名空間通過一些類提供對訪問控制列表的訪問。DiectorySecurity:該類指定目錄的訪問控制和審核安全。指定系統目錄的訪問許可權以及訪問嘗試的審核方式。FileSecurity:該類指定系統文件的訪問許可權以及如何審核訪問嘗試。

     下麵介紹一下文件許可權操作的類和方法:

      (1).FileStream類GetAccessControl():檢索文件的安全對象:
[SecuritySafeCritical]
public FileSecurity GetAccessControl()
{
    if (this._handle.IsClosed)
    {
        __Error.FileNotOpen();
    }
    return new FileSecurity(this._handle, this._fileName, AccessControlSections.Group | AccessControlSections.Owner | AccessControlSections.Access);
}
[SecurityCritical, SecurityPermission(SecurityAction.Assert, UnmanagedCode=true)]
internal FileSecurity(SafeFileHandle handle, string fullPath, AccessControlSections includeSections) : base(false, handle, includeSections, false)
{
    if (fullPath != null)
    {
        new FileIOPermission(FileIOPermissionAccess.NoAccess, AccessControlActions.View, fullPath).Demand();
    }
    else
    {
        new FileIOPermission(PermissionState.Unrestricted).Demand();
    }
}
    (2).FileStream類SetAccessControl():保存設置。
[SecuritySafeCritical]
public void SetAccessControl(FileSecurity fileSecurity)
{
    if (fileSecurity == null)
    {
        throw new ArgumentNullException("fileSecurity");
    }
    if (this._handle.IsClosed)
    {
        __Error.FileNotOpen();
    }
    fileSecurity.Persist(this._handle, this._fileName);
}

  2.文件共用操作實例:

    /// <summary>
    /// 共用文檔操作
    /// </summary>
    public class FileSharingOperationHelper
    {
        public static bool ConnectState(string path)
        {
            if (string.IsNullOrEmpty(path))
            {
                throw new ArgumentNullException(path);
            }
            return ConnectState(path, "", "");
        }

        /// <summary>
        /// 連接遠程共用文件夾
        /// </summary>
        /// <param name="path">遠程共用文件夾的路徑</param>
        /// <param name="userName">用戶名</param>
        /// <param name="passWord">密碼</param>
        /// <returns></returns>
        public static bool ConnectState(string path, string userName, string passWord)
        {
            var proc = new Process();
            try
            {
                proc.StartInfo.FileName = "cmd.exe";
                proc.StartInfo.UseShellExecute = false;
                proc.StartInfo.RedirectStandardInput = true;
                proc.StartInfo.RedirectStandardOutput = true;
                proc.StartInfo.RedirectStandardError = true;
                proc.StartInfo.CreateNoWindow = true;
                proc.Start();
                var dosLine = "net use " + path + " " + passWord + " /user:" + userName;
                proc.StandardInput.WriteLine(dosLine);
                proc.StandardInput.WriteLine("exit");
                while (!proc.HasExited)
                {
                    proc.WaitForExit(1000);
                }
                var errormsg = proc.StandardError.ReadToEnd();
                proc.StandardError.Close();
                if (!string.IsNullOrEmpty(errormsg))
                {
                    throw new Exception(errormsg);
                }
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
            finally
            {
                proc.Close();
                proc.Dispose();
            }
            return true;
        }

        /// <summary>
        /// 向遠程文件夾保存本地內容,或者從遠程文件夾下載文件到本地
        /// </summary>
        /// <param name="src">要保存的文件的路徑,如果保存文件到共用文件夾,這個路徑就是本地文件路徑如:@"D:\1.avi"</param>
        /// <param name="dst">保存文件的路徑,不含名稱及擴展名</param>
        /// <param name="fileName">保存文件的名稱以及擴展名</param>
        public static void Transport(string src, string dst, string fileName)
        {
            if (string.IsNullOrEmpty(src))
            {
                throw new ArgumentNullException(src);
            }
            if (string.IsNullOrEmpty(dst))
            {
                throw new ArgumentNullException(dst);
            }
            if (string.IsNullOrEmpty(fileName))
            {
                throw new ArgumentNullException(fileName);
            }
            FileStream inFileStream = null;
            FileStream outFileStream = null;
            try
            {
                inFileStream = new FileStream(src, FileMode.Open);
                if (!	   

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

-Advertisement-
Play Games
更多相關文章
  • 文件同步傳輸工具比較多,傳輸的方式也比較多,比如:FTP、共用、HTTP等,我這裡要講的就是基於HTTP協議的WEB API實現批量文件由一個伺服器同步快速傳輸到其它多個伺服器這樣的一個工具(簡稱:一端到多端的文件同步工具) 一、設計原理: 1.使用的技術:WinForm、WebApi 1.1 Wi ...
  • 問題描述:如題。 使用工具:騰訊雲Windows Server 2012 R2 數據中心版 64位中文版。 操作步驟: 1、伺服器管理器->IIS ...
  • 在上一篇文章中我用遞歸方法實現了管理菜單,在上一節我也提到要考慮用緩存,也算是學習一下.Net Core的緩存機制。 關於.Net Core的緩存,官方有三種實現: 1.In Memory Caching 我理解是在內容中實現,這種方法適用於單伺服器的生產環境。 2.a Distributed Ca ...
  • 什麼是Fluent API? 官方答案:EF 中內嵌的約定將 POCO 類映射到表。但是,有時您無法或不想遵守這些約定,需要將實體映射到約定指示外的其他對象,所以Fluent API和註解都是一種方法,這兩種方法是用來配置EF,在映射屬性時繞開約定。詳情參考(https://msdn.microso ...
  • Smobiler是一個在VS環境中使用.Net語言來開發APP的開發平臺,也許比Xamarin更方便 ...
  • Autofac在提供之前那些方法的時候, 同時提供了五個事件, 這一篇就看一下這幾個事件. 一、五大事件 看一下結果: 額, 首先我得說明一下, 輸出的順序和我寫事件的順序是沒有關係的, 不是說, 我事件寫在前面, 輸出就在前面. 從這張圖上, 能看到, 對象創建時, 構造函數的調用時在中間的. 其 ...
  • 具體方法: 控制台輸出:Console.WriteLine(Days()); //輸出結果: //演算法原理: //第一個元素加1天和第二個元素比較,日期不同的話, 直接跳出迴圈,從下一個元素繼續對比 //第一個元素加1天與第二個元素比較,如果日期相同則最大連續天數加1,然後第二個元素加1天與第三個元 ...
  • 在前幾篇Log4net入門文件的講述過程中,我們在使用log4net的類中都要編寫如下一行代碼: 1 private static log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurr ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...