• C# FTP删除文件以及文件夹


    1.FTP文件操作类   FtpClient

      1 using System;
      2 using System.Collections.Generic;
      3 using System.Linq;
      4 using System.Text;
      5 using System.IO;
      6 using System.Net;
      7 using System.Xml.Serialization;
      8 using System.Threading;
      9 using System.Data;
     10 using System.Data.SqlClient;
     11 using System.Xml;
     12 using System.Xml.Linq;
     13 
     14 namespace XMDD.NewWeb
     15 {
     16     public class FtpClient
     17     {
     18         private string _ftpServerIp;
     19         private string _ftpRemotePath;
     20 
     21         public string FtpRemotePath
     22         {
     23             get { return _ftpRemotePath; }
     24             set 
     25             { 
     26                 _ftpRemotePath = value;
     27                 if (!string.IsNullOrWhiteSpace(_ftpRemotePath))
     28                     this._ftpUri = "ftp://" + _ftpServerIp + "/" + _ftpRemotePath + "/";
     29                 else
     30                     this._ftpUri = "ftp://" + _ftpServerIp + "/";
     31             }
     32         }
     33         private string _ftpUserId;
     34         private string _ftpPassword;
     35         private string _localSavePath;
     36         private string _ftpUri;
     37 
     38         public void InitFtp(string ftpServerIp, string ftpRemotePath, string ftpUserId, string ftpPassword, string localSavePath)
     39         {
     40             this._ftpServerIp = ftpServerIp;
     41             this._ftpUserId = ftpUserId;
     42             this._ftpPassword = ftpPassword;
     43             this._localSavePath = localSavePath;
     44 
     45             FtpRemotePath = ftpRemotePath;
     46             if (!string.IsNullOrWhiteSpace(this._localSavePath) && !Directory.Exists(this._localSavePath))
     47             {
     48                 try
     49                 {
     50                     Directory.CreateDirectory(this._localSavePath);
     51                 }
     52                 catch { }
     53             }
     54         }
     55 
     56         public void InitFtp(string ftpServerIp, string ftpUserId, string ftpPassword, string localSavePath)
     57         {
     58            InitFtp(ftpServerIp,"",ftpUserId,ftpPassword,localSavePath);
     59         }
     60 
     61         /// <summary>
     62         /// 上传
     63         /// </summary>
     64         /// <param name="filename"></param>
     65         public void Upload(string filename)
     66         {
     67             FileInfo fileInf = new FileInfo(filename);
     68             string uri = _ftpUri + fileInf.Name;
     69             FtpWebRequest reqFTP;
     70  
     71             reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri));
     72             reqFTP.Credentials = new NetworkCredential(_ftpUserId, _ftpPassword);
     73             reqFTP.KeepAlive = false;
     74             reqFTP.Method = WebRequestMethods.Ftp.UploadFile;
     75             reqFTP.UseBinary = true;
     76             reqFTP.ContentLength = fileInf.Length;
     77             int buffLength = 2048;
     78             byte[] buff = new byte[buffLength];
     79             int contentLen;
     80             FileStream fs = null;
     81             try
     82             {
     83                 fs = fileInf.OpenRead();
     84                 Stream strm = reqFTP.GetRequestStream();
     85                 contentLen = fs.Read(buff, 0, buffLength);
     86                 while (contentLen != 0)
     87                 {
     88                     strm.Write(buff, 0, contentLen);
     89                     contentLen = fs.Read(buff, 0, buffLength);
     90                 }
     91                 strm.Close();
     92             }
     93             catch (Exception ex)
     94             {
     95                 throw ex;
     96             }
     97             finally
     98             {
     99                 if(fs!=null)
    100                     fs.Close();
    101             }
    102         }
    103 
    104         public void Upload(byte[] buffer, string filename)
    105         {
    106             string uri = _ftpUri + filename;
    107             FtpWebRequest reqFTP;
    108 
    109             reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri));
    110             reqFTP.Credentials = new NetworkCredential(_ftpUserId, _ftpPassword);
    111             reqFTP.KeepAlive = false;
    112             reqFTP.Method = WebRequestMethods.Ftp.UploadFile;
    113             reqFTP.UseBinary = true;
    114             reqFTP.ContentLength = buffer.Length;
    115             try
    116             {
    117                 Stream strm = reqFTP.GetRequestStream();
    118                 strm.Write(buffer, 0, buffer.Length);
    119                 strm.Close();
    120             }
    121             catch (Exception ex)
    122             {
    123                 throw ex;
    124             }
    125         }
    126 
    127         public void Upload(string ftpUri,string ftpUserId,string ftpPassword, string filename)
    128         {
    129             FileStream fs = null;
    130             try
    131             {
    132                 FileInfo fileInf = new FileInfo(filename);
    133                 string uri = ftpUri + fileInf.Name;
    134                 FtpWebRequest reqFTP;
    135 
    136                 reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri));
    137                 reqFTP.Credentials = new NetworkCredential(ftpUserId, ftpPassword);
    138                 reqFTP.KeepAlive = false;
    139                 reqFTP.Method = WebRequestMethods.Ftp.UploadFile;
    140                 reqFTP.UseBinary = true;
    141                 reqFTP.ContentLength = fileInf.Length;
    142                 int buffLength = 2048;
    143                 byte[] buff = new byte[buffLength];
    144                 int contentLen;
    145                 fs = fileInf.OpenRead();
    146            
    147                 Stream strm = reqFTP.GetRequestStream();
    148                 contentLen = fs.Read(buff, 0, buffLength);
    149                 while (contentLen != 0)
    150                 {
    151                     strm.Write(buff, 0, contentLen);
    152                     contentLen = fs.Read(buff, 0, buffLength);
    153                 }
    154                 strm.Close();
    155             }
    156             catch (Exception ex)
    157             {
    158                 throw ex;
    159             }
    160             finally
    161             {
    162                 if (fs != null)
    163                     fs.Close();
    164             }
    165         }
    166  
    167         /// <summary>
    168         /// 下载
    169         /// </summary>
    170         /// <param name="filePath"></param>
    171         /// <param name="fileName"></param>
    172         public string Download(string fileName)
    173         {
    174             if (string.IsNullOrEmpty(fileName))
    175                 return null;
    176 
    177             FtpWebRequest reqFTP;
    178             FileStream outputStream=null;
    179             FileStream fs = null;
    180             string content = "";
    181             try
    182             {
    183                 outputStream = new FileStream(_localSavePath + "\" + fileName, FileMode.Create);
    184 
    185                 reqFTP = (FtpWebRequest)WebRequest.Create(new Uri(_ftpUri + fileName));
    186 
    187                 reqFTP.Method = WebRequestMethods.Ftp.DownloadFile;
    188                 reqFTP.UseBinary = true;
    189                 reqFTP.Credentials = new NetworkCredential(_ftpUserId, _ftpPassword);
    190                 var response = (FtpWebResponse)reqFTP.GetResponse();
    191                 var ftpStream = response.GetResponseStream();
    192                 var cl = response.ContentLength;
    193                 var bufferSize = 2048;
    194                 int readCount;
    195                 byte[] buffer = new byte[bufferSize];
    196  
    197                 readCount = ftpStream.Read(buffer, 0, bufferSize);
    198                 while (readCount > 0)
    199                 {
    200                     outputStream.Write(buffer, 0, readCount);
    201                     readCount = ftpStream.Read(buffer, 0, bufferSize);
    202                 }
    203  
    204                 ftpStream.Close();
    205                 outputStream.Close();
    206                 response.Close();
    207                 //Buffer.Log(string.Format("Ftp文件{1}下载成功!" , DateTime.Now.ToString(), fileName));
    208 
    209                 fs = new FileStream(_localSavePath + "\" + fileName, FileMode.Open);
    210                 var sr = new StreamReader(fs);
    211 
    212                 content = sr.ReadToEnd();
    213 
    214                 sr.Close();
    215                 fs.Close();
    216 
    217                 Delete(fileName);
    218             }
    219             catch (Exception ex)
    220             {
    221                 if (outputStream != null)
    222                     outputStream.Close();
    223                 if (fs != null)
    224                     fs.Close();
    225                 throw ex;
    226             }
    227 
    228             return content;
    229 
    230         }
    231 
    232         public byte[] DownloadByte(string fileName)
    233         {
    234             if (string.IsNullOrEmpty(fileName))
    235                 return null;
    236 
    237             FtpWebRequest reqFTP;
    238             byte[] buff = null; 
    239             try
    240             {
    241 
    242                 reqFTP = (FtpWebRequest)WebRequest.Create(new Uri(_ftpUri + fileName));
    243 
    244                 reqFTP.Method = WebRequestMethods.Ftp.DownloadFile;
    245                 reqFTP.UseBinary = true;
    246                 reqFTP.Credentials = new NetworkCredential(_ftpUserId, _ftpPassword);
    247                 var response = (FtpWebResponse)reqFTP.GetResponse();
    248                 var ftpStream = response.GetResponseStream();
    249 
    250                 MemoryStream stmMemory = new MemoryStream();
    251                 byte[] buffer = new byte[64 * 1024];
    252                 int i;
    253                 while ((i = ftpStream.Read(buffer, 0, buffer.Length)) > 0)
    254                 {
    255                     stmMemory.Write(buffer, 0, i);
    256                 }
    257                 buff = stmMemory.ToArray();
    258                 stmMemory.Close();
    259                 ftpStream.Close();
    260                 response.Close();
    261             }
    262             catch (Exception ex)
    263             {
    264                 throw ex;
    265             }
    266 
    267             return buff;
    268 
    269         }
    270 
    271         /// <summary>
    272         /// 删除文件
    273         /// </summary>
    274         /// <param name="fileName"></param>
    275         public void Delete(string fileName)
    276         {
    277             try
    278             {
    279                 string uri = _ftpUri + fileName;
    280                 FtpWebRequest reqFTP;
    281                 reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri));
    282 
    283                 reqFTP.Credentials = new NetworkCredential(_ftpUserId, _ftpPassword);
    284                 reqFTP.KeepAlive = false;
    285                 reqFTP.Method = WebRequestMethods.Ftp.DeleteFile;
    286  
    287                 string result = String.Empty;
    288                 FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
    289                 long size = response.ContentLength;
    290                 Stream datastream = response.GetResponseStream();
    291                 StreamReader sr = new StreamReader(datastream);
    292                 result = sr.ReadToEnd();
    293                 sr.Close();
    294                 datastream.Close();
    295                 response.Close();
    296                 //Buffer.Log(string.Format("Ftp文件{1}删除成功!", DateTime.Now.ToString(), fileName));
    297             }
    298             catch (Exception ex)
    299             {
    300                 throw ex;
    301             }
    302         }
    303  
    304         /// <summary>
    305         /// 删除文件夹(只针对空文件夹)
    306         /// </summary>
    307         /// <param name="folderName"></param>
    308         public void RemoveDirectory(string folderName)
    309         {
    310             try
    311             {
    312                 string uri = _ftpUri + folderName;
    313                 FtpWebRequest reqFTP;
    314                 reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri));
    315 
    316                 reqFTP.Credentials = new NetworkCredential(_ftpUserId, _ftpPassword);
    317                 reqFTP.KeepAlive = false;
    318                 reqFTP.Method = WebRequestMethods.Ftp.RemoveDirectory;
    319  
    320                 string result = String.Empty;
    321                 FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
    322                 long size = response.ContentLength;
    323                 Stream datastream = response.GetResponseStream();
    324                 StreamReader sr = new StreamReader(datastream);
    325                 result = sr.ReadToEnd();
    326                 sr.Close();
    327                 datastream.Close();
    328                 response.Close();
    329             }
    330             catch (Exception ex)
    331             {
    332                 throw ex;
    333             }
    334         }
    335 
    336         /// <summary>
    337         /// 删除文件夹以及其下面的所有内容
    338         /// </summary>
    339         /// <param name="ftp">ftp</param>
    340         public void DeleteFtpDirWithAll(FtpClient ftp)
    341         {
    342             string[] fileList = ftp.GetFileList("");//获取所有文件列表(仅文件)
    343             //1.首先删除所有的文件
    344             if (fileList != null && fileList.Length > 0)
    345             {
    346                 foreach (string file in fileList)
    347                 {
    348                     ftp.Delete(file);
    349                 }
    350             }
    351 
    352             //获取所有文件夹列表(仅文件夹)
    353             string[] emptyDriList = ftp.GetDirectoryList();
    354             foreach (string dir in emptyDriList)
    355             {
    356                 //有时候会出现空的子目录,这时候要排除
    357                 if (string.IsNullOrWhiteSpace(dir))
    358                 {
    359                     continue;
    360                 }
    361 
    362                 string curDir = "/" + dir;
    363                 ftp.FtpRemotePath = ftp.FtpRemotePath + curDir;
    364                 //是否有子文件夹存在
    365                 if (ftp.GetDirectoryList() != null && ftp.GetDirectoryList().Length > 0)
    366                 {
    367                     DeleteFtpDirWithAll(ftp);//如果有就继续递归
    368                 }
    369                 ftp.FtpRemotePath = ftp.FtpRemotePath.Replace(curDir, "");//回退到上级目录以删除其本身
    370                 ftp.RemoveDirectory(dir);//删除当前文件夹
    371             }
    372         }
    373 
    374         /// <summary>
    375         /// 获取当前目录下明细(包含文件和文件夹)
    376         /// </summary>
    377         /// <returns></returns>
    378         public string[] GetFilesDetailList()
    379         {
    380             //string[] downloadFiles;
    381             try
    382             {
    383                 StringBuilder result = new StringBuilder();
    384                 FtpWebRequest ftp;
    385                 ftp = (FtpWebRequest)FtpWebRequest.Create(new Uri(_ftpUri));
    386                 ftp.Credentials = new NetworkCredential(_ftpUserId, _ftpPassword);
    387                 ftp.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
    388                 WebResponse response = ftp.GetResponse();
    389                 StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.Default);
    390 
    391                 //while (reader.Read() > 0)
    392                 //{
    393 
    394                 //}
    395                 string line = reader.ReadLine();
    396                 //line = reader.ReadLine();
    397                 //line = reader.ReadLine();
    398 
    399                 while (line != null)
    400                 {
    401                     result.Append(line);
    402                     result.Append("
    ");
    403                     line = reader.ReadLine();
    404                 }
    405                 if (result.Length == 0)
    406                     return null;
    407                 result.Remove(result.ToString().LastIndexOf("
    "), 1);
    408                 reader.Close();
    409                 response.Close();
    410                 return result.ToString().Split('
    ');
    411             }
    412             catch (Exception ex)
    413             {
    414                 
    415 
    416                 return null;
    417             }
    418         }
    419  
    420         /// <summary>
    421         /// 获取当前目录下文件列表(仅文件)
    422         /// </summary>
    423         /// <returns></returns>
    424         public string[] GetFileList(string mask)
    425         {
    426             string[] downloadFiles=null;
    427             StringBuilder result = new StringBuilder();
    428             FtpWebRequest reqFTP;
    429             try
    430             {
    431                 reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(_ftpUri));
    432                 reqFTP.UseBinary = true;
    433                 reqFTP.Credentials = new NetworkCredential(_ftpUserId, _ftpPassword);
    434                 reqFTP.Method = WebRequestMethods.Ftp.ListDirectory;
    435                 WebResponse response = reqFTP.GetResponse();
    436                 StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.Default);
    437  
    438                 string line = reader.ReadLine();
    439                 while (line != null)
    440                 {
    441                     if (mask.Trim() != string.Empty && mask.Trim() != "*.*")
    442                     {
    443  
    444                         string mask_ = mask.Substring(0, mask.IndexOf("*"));
    445                         if (line.Substring(0, mask_.Length) == mask_)
    446                         {
    447                             result.Append(line);
    448                             result.Append("
    ");
    449                         }
    450                     }
    451                     else
    452                     {
    453                         result.Append(line);
    454                         result.Append("
    ");
    455                     }
    456                     line = reader.ReadLine();
    457                 }
    458                 if (result.Length == 0)
    459                     return new string[]{};
    460                 result.Remove(result.ToString().LastIndexOf('
    '), 1);
    461                 reader.Close();
    462                 response.Close();
    463                 downloadFiles= result.ToString().Split('
    ');
    464             }
    465             catch (Exception ex)
    466             {
    467                 return new string[] { };
    468             }
    469 
    470             if (downloadFiles == null)
    471                 downloadFiles = new string[] { };
    472             return downloadFiles;
    473         }
    474 
    475         public string GetSingleFile()
    476         {
    477             var list = GetFileList("*.*");
    478 
    479             if (list != null && list.Length > 0)
    480                 return list[0];
    481             else
    482                 return null;
    483         }
    484  
    485         /// <summary>
    486         /// 获取当前目录下所有的文件夹列表(仅文件夹)
    487         /// </summary>
    488         /// <returns></returns>
    489         public string[] GetDirectoryList()
    490         {
    491             string[] drectory = GetFilesDetailList();
    492             if (drectory == null)
    493                 return null;
    494             string m = string.Empty;
    495             foreach (string str in drectory)
    496             {
    497                 int dirPos = str.IndexOf("<DIR>");
    498                 if (dirPos>0)
    499                 {
    500                     /*判断 Windows 风格*/
    501                     m += str.Substring(dirPos + 5).Trim() + "
    ";
    502                 }
    503                 else if (str.Trim().Substring(0, 1).ToUpper() == "D")
    504                 {
    505                     /*判断 Unix 风格*/
    506                     string dir = str.Substring(54).Trim();
    507                     if (dir != "." && dir != "..")
    508                     {
    509                         m += dir + "
    "; 
    510                     }
    511                 }
    512             }
    513  
    514             char[] n = new char[] { '
    ' };
    515             return m.Split(n);
    516         }
    517  
    518         /// <summary>
    519         /// 判断当前目录下指定的子目录是否存在
    520         /// </summary>
    521         /// <param name="RemoteDirectoryName">指定的目录名</param>
    522         public bool DirectoryExist(string RemoteDirectoryName)
    523         {
    524             string[] dirList = GetDirectoryList();
    525             if (dirList != null)
    526             {
    527                 foreach (string str in dirList)
    528                 {
    529                     if (str.Trim() == RemoteDirectoryName.Trim())
    530                     {
    531                         return true;
    532                     }
    533                 }
    534             }
    535             return false;
    536         }
    537  
    538         /// <summary>
    539         /// 判断当前目录下指定的文件是否存在
    540         /// </summary>
    541         /// <param name="RemoteFileName">远程文件名</param>
    542         public bool FileExist(string RemoteFileName)
    543         {
    544             string[] fileList = GetFileList("*.*");
    545             foreach (string str in fileList)
    546             {
    547                 if (str.Trim() == RemoteFileName.Trim())
    548                 {
    549                     return true;
    550                 }
    551             }
    552             return false;
    553         }
    554  
    555         /// <summary>
    556         /// 创建文件夹
    557         /// </summary>
    558         /// <param name="dirName"></param>
    559         public void MakeDir(string dirName)
    560         {
    561             FtpWebRequest reqFTP;
    562             try
    563             {
    564                 // dirName = name of the directory to create.
    565                 reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(_ftpUri + dirName));
    566                 reqFTP.Method = WebRequestMethods.Ftp.MakeDirectory;
    567                 reqFTP.UseBinary = true;
    568                 reqFTP.Credentials = new NetworkCredential(_ftpUserId, _ftpPassword);
    569                 FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
    570                 Stream ftpStream = response.GetResponseStream();
    571  
    572                 ftpStream.Close();
    573                 response.Close();
    574             }
    575             catch (Exception ex)
    576             {
    577                 throw ex;
    578             }
    579         }
    580  
    581         /// <summary>
    582         /// 获取指定文件大小
    583         /// </summary>
    584         /// <param name="filename"></param>
    585         /// <returns></returns>
    586         public long GetFileSize(string filename)
    587         {
    588             FtpWebRequest reqFTP;
    589             long fileSize = 0;
    590             try
    591             {
    592                 reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(_ftpUri + filename));
    593                 reqFTP.Method = WebRequestMethods.Ftp.GetFileSize;
    594                 reqFTP.UseBinary = true;
    595                 reqFTP.Credentials = new NetworkCredential(_ftpUserId, _ftpPassword);
    596                 FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
    597                 Stream ftpStream = response.GetResponseStream();
    598                 fileSize = response.ContentLength;
    599  
    600                 ftpStream.Close();
    601                 response.Close();
    602             }
    603             catch (Exception ex)
    604             {
    605                 //throw new Exception("FtpWeb:GetFileSize Error --> " + ex.Message);
    606             }
    607             return fileSize;
    608         }
    609  
    610         /// <summary>
    611         /// 改名
    612         /// </summary>
    613         /// <param name="currentFilename"></param>
    614         /// <param name="newFilename"></param>
    615         public void ReName(string currentFilename, string newFilename)
    616         {
    617             FtpWebRequest reqFTP;
    618             try
    619             {
    620                 reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(_ftpUri + currentFilename));
    621                 reqFTP.Method = WebRequestMethods.Ftp.Rename;
    622                 reqFTP.RenameTo = newFilename;
    623                 reqFTP.UseBinary = true;
    624                 reqFTP.Credentials = new NetworkCredential(_ftpUserId, _ftpPassword);
    625                 FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
    626                 Stream ftpStream = response.GetResponseStream();
    627  
    628                 ftpStream.Close();
    629                 response.Close();
    630             }
    631             catch (Exception ex)
    632             {
    633                 throw ex;
    634             }
    635         }
    636  
    637         /// <summary>
    638         /// 移动文件
    639         /// </summary>
    640         /// <param name="currentFilename"></param>
    641         /// <param name="newFilename"></param>
    642         public void MovieFile(string currentFilename, string newDirectory)
    643         {
    644             ReName(currentFilename, newDirectory);
    645         }
    646  
    647     }
    648 }
    View Code

    2.调用 DictionaryDelete

     1   //获取FTP配置信息
     2         string ftpServerIP = System.Configuration.ConfigurationManager.AppSettings["ConfigFTPAddress"].ToString();//FTP地址
     3         string ftpUserName = System.Configuration.ConfigurationManager.AppSettings["ConfigFTPLoginName"].ToString();//FTP登录用户名
     4         string ftpUserPwd = System.Configuration.ConfigurationManager.AppSettings["ConfigFTPLoginPwd"].ToString();//FTP登录密码
     5         string dirName = "10.6.1.140";//这个IP地址只是一个文件夹的名称
     6 
     7         /// <summary>
     8         /// 删除文件夹
     9         /// </summary>
    10         private void DictionaryDelete() 
    11         {        
    12             FtpClient ftp = new FtpClient();
    13             ftp.InitFtp(ftpServerIP, ftpUserName, ftpUserPwd, "");
    14             ftp.FtpRemotePath = dirName;
    15             ftp.DeleteFtpDirWithAll(ftp);
    16         }
    17 
    18         /// <summary>
    19         /// 创建文件夹
    20         /// </summary>
    21         private void DictionaryCreate() 
    22         {
    23             FtpClient ftp = new FtpClient();
    24             ftp.InitFtp(ftpServerIP, ftpUserName, ftpUserPwd, "");
    25             if (!ftp.DirectoryExist(dirName))
    26             {
    27                 ftp.MakeDir(dirName);
    28             }
    29         }
    View Code

    3.说明,主要方法是  FtpClient 类中的 DeleteFtpDirWithAll 方法

    删除前:

    删除后:

  • 相关阅读:
    2021/9/23(桶排序+基数排序 结束排序)
    【转】十大经典排序算法(动画演示)
    如何测试代码执行时间
    图解排序算法之归并排序(转)
    TED演讲:拖延症人群的内心世界
    IntelliJ IDEA入门
    支付宝支付入门
    Spring Cloud 入门
    软件设计模式类型介绍
    《小狗钱钱2》读书笔记
  • 原文地址:https://www.cnblogs.com/programsky/p/FTP.html
Copyright © 2020-2023  润新知