FtpClient.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. using System.Net;
  6. using System.Text;
  7. using System.Threading.Tasks;
  8. namespace BaseLibComm
  9. {
  10. public class FtpClient
  11. {
  12. #region 构造函数
  13. /// <summary>
  14. /// 创建FTP工具
  15. /// <para>
  16. /// 默认不使用SSL,使用二进制传输方式,使用被动模式
  17. /// </para>
  18. /// </summary>
  19. /// <param name="host">主机名称</param>
  20. /// <param name="userId">用户名</param>
  21. /// <param name="password">密码</param>
  22. public FtpClient(string host, string userId, string password)
  23. : this(host, userId, password, 21, null, false, true, true)
  24. {
  25. }
  26. /// <summary>
  27. /// 创建FTP工具
  28. /// </summary>
  29. /// <param name="host">主机名称</param>
  30. /// <param name="userId">用户名</param>
  31. /// <param name="password">密码</param>
  32. /// <param name="port">端口</param>
  33. /// <param name="enableSsl">允许Ssl</param>
  34. /// <param name="proxy">代理</param>
  35. /// <param name="useBinary">允许二进制</param>
  36. /// <param name="usePassive">允许被动模式</param>
  37. public FtpClient(string host, string userId, string password, int port, IWebProxy proxy, bool enableSsl, bool useBinary, bool usePassive)
  38. {
  39. this.UserId = userId;
  40. this.Password = password;
  41. if (host.ToLower().StartsWith("ftp://"))
  42. {
  43. this.host = host;
  44. }
  45. else
  46. {
  47. this.host = "ftp://" + host;
  48. }
  49. this.Port = port;
  50. this.Proxy = proxy;
  51. this.EnableSsl = enableSsl;
  52. this.UseBinary = useBinary;
  53. this.UsePassive = usePassive;
  54. }
  55. #endregion
  56. #region Property
  57. private string host = string.Empty;
  58. public string Host
  59. {
  60. get
  61. {
  62. return this.host ?? string.Empty;
  63. }
  64. }
  65. public string UserId { get; } = string.Empty;// 登录用户名
  66. public string Password { get; } = string.Empty;// 密码
  67. public IWebProxy Proxy { get; set; } = null;// 代理
  68. public int Port { get; set; } = 21;// 端口
  69. public bool EnableSsl { get; } = false;// EnableSsl 设置是否允许Ssl
  70. public bool UsePassive { get; set; } = true;// 被动模式 使用被动模式
  71. public bool UseBinary { get; set; } = true;// 二进制方式
  72. private string remotePath = "/";
  73. public string RemotePath //返回FTP服务器上的当前路径(可以是 / 或 /a/../ 的形式)
  74. {
  75. get
  76. {
  77. return remotePath;
  78. }
  79. set
  80. {
  81. string result = "/";
  82. if (!string.IsNullOrEmpty(value) && value != "/")
  83. {
  84. result = "/" + value.TrimStart('/').TrimEnd('/') + "/";
  85. }
  86. this.remotePath = result;
  87. }
  88. }
  89. #endregion
  90. #region 创建一个FTP连接
  91. /// <summary>
  92. /// 创建一个FTP请求
  93. /// </summary>
  94. /// <param name="url">请求地址</param>
  95. /// <param name="method">请求方法</param>
  96. /// <returns>FTP请求</returns>
  97. private FtpWebRequest CreateRequest(string url, string method)
  98. {
  99. //建立连接
  100. FtpWebRequest request = (FtpWebRequest)WebRequest.Create(url);
  101. request.Credentials = new NetworkCredential(UserId, Password);
  102. request.Proxy = Proxy;
  103. request.KeepAlive = false;//命令执行完毕之后关闭连接
  104. request.UseBinary = UseBinary;
  105. request.UsePassive = UsePassive;
  106. request.EnableSsl = EnableSsl;
  107. request.Method = method;
  108. return request;
  109. }
  110. #endregion
  111. #region 上传一个文件到远端路径下
  112. /// <summary>
  113. /// 把文件上传到FTP服务器的RemotePath下
  114. /// </summary>
  115. /// <param name="localFile">本地文件信息</param>
  116. /// <param name="remoteFileName">要保存到FTP文件服务器上的名称</param>
  117. public bool Upload(FileInfo localFile, string remoteFileName)
  118. {
  119. bool result = false;
  120. if (localFile.Exists)
  121. {
  122. string url = Host.TrimEnd('/') + RemotePath + remoteFileName;
  123. FtpWebRequest request = CreateRequest(url, WebRequestMethods.Ftp.UploadFile);
  124. //上传数据
  125. using (Stream rs = request.GetRequestStream())
  126. using (FileStream fs = localFile.OpenRead())
  127. {
  128. byte[] buffer = new byte[4096];//4K
  129. int count = fs.Read(buffer, 0, buffer.Length);
  130. while (count > 0)
  131. {
  132. rs.Write(buffer, 0, count);
  133. count = fs.Read(buffer, 0, buffer.Length);
  134. }
  135. fs.Close();
  136. result = true;
  137. }
  138. return result;
  139. }
  140. throw new Exception(string.Format("本地文件不存在,文件路径:{0}", localFile.FullName));
  141. }
  142. #endregion
  143. #region 从FTP服务器上下载文件
  144. /// <summary>
  145. /// 从当前目录下下载文件
  146. /// <para>
  147. /// 如果本地文件存在,则从本地文件结束的位置开始下载.
  148. /// </para>
  149. /// </summary>
  150. /// <param name="serverName">服务器上的文件名称</param>
  151. /// <param name="localName">本地文件名称</param>
  152. /// <returns>返回一个值,指示是否下载成功</returns>
  153. public bool Download(string serverName, string localName)
  154. {
  155. bool result = false;
  156. using (FileStream fs = new FileStream(localName, FileMode.OpenOrCreate)) //创建或打开本地文件
  157. {
  158. //建立连接
  159. string url = Host.TrimEnd('/') + RemotePath + serverName;
  160. FtpWebRequest request = CreateRequest(url, WebRequestMethods.Ftp.DownloadFile);
  161. request.ContentOffset = fs.Length;
  162. using (FtpWebResponse response = (FtpWebResponse)request.GetResponse())
  163. {
  164. fs.Position = fs.Length;
  165. byte[] buffer = new byte[4096];//4K
  166. int count = response.GetResponseStream().Read(buffer, 0, buffer.Length);
  167. while (count > 0)
  168. {
  169. fs.Write(buffer, 0, count);
  170. count = response.GetResponseStream().Read(buffer, 0, buffer.Length);
  171. }
  172. response.GetResponseStream().Close();
  173. }
  174. result = true;
  175. }
  176. return result;
  177. }
  178. #endregion
  179. #region 重命名FTP服务器上的文件
  180. /// <summary>
  181. /// 文件更名
  182. /// </summary>
  183. /// <param name="oldFileName">原文件名</param>
  184. /// <param name="newFileName">新文件名</param>
  185. /// <returns>返回一个值,指示更名是否成功</returns>
  186. public bool Rename(string oldFileName, string newFileName)
  187. {
  188. bool result = false;
  189. //建立连接
  190. string url = Host.TrimEnd('/') + RemotePath + oldFileName;
  191. FtpWebRequest request = CreateRequest(url, WebRequestMethods.Ftp.Rename);
  192. request.RenameTo = newFileName;
  193. using (FtpWebResponse response = (FtpWebResponse)request.GetResponse())
  194. {
  195. result = true;
  196. }
  197. return result;
  198. }
  199. #endregion
  200. #region 从当前目录下获取文件列表
  201. /// <summary>
  202. /// 获取当前目录下文件列表
  203. /// </summary>
  204. /// <returns></returns>
  205. public List<string> GetFileList()
  206. {
  207. List<string> result = new List<string>();
  208. //建立连接
  209. string url = Host.TrimEnd('/') + RemotePath;//string url = (Host +":"+ Port).TrimEnd('/') + RemotePath;
  210. FtpWebRequest request = CreateRequest(url, WebRequestMethods.Ftp.ListDirectory);
  211. using (FtpWebResponse response = (FtpWebResponse)request.GetResponse())
  212. {
  213. StreamReader reader = new StreamReader(response.GetResponseStream(), System.Text.Encoding.Default);//中文文件名
  214. string line = reader.ReadLine();
  215. while (line != null)
  216. {
  217. result.Add(line);
  218. line = reader.ReadLine();
  219. }
  220. }
  221. return result;
  222. }
  223. #endregion
  224. #region 从FTP服务器上获取文件和文件夹列表
  225. /// <summary>
  226. /// 获取详细列表 从FTP服务器上获取文件和文件夹列表
  227. /// </summary>
  228. /// <returns></returns>
  229. public List<string> GetFileDetails()
  230. {
  231. List<string> result = new List<string>();
  232. //建立连接
  233. string url = Host.TrimEnd('/') + RemotePath;
  234. FtpWebRequest request = CreateRequest(url, WebRequestMethods.Ftp.ListDirectoryDetails);
  235. using (FtpWebResponse response = (FtpWebResponse)request.GetResponse())
  236. {
  237. StreamReader reader = new StreamReader(response.GetResponseStream(), System.Text.Encoding.Default);//中文文件名
  238. string line = reader.ReadLine();
  239. while (line != null)
  240. {
  241. result.Add(line);
  242. line = reader.ReadLine();
  243. }
  244. }
  245. return result;
  246. }
  247. #endregion
  248. #region 从FTP服务器上删除文件
  249. /// <summary>
  250. /// 删除FTP服务器上的文件
  251. /// </summary>
  252. /// <param name="fileName">文件名称</param>
  253. /// <returns>返回一个值,指示是否删除成功</returns>
  254. public bool DeleteFile(string fileName)
  255. {
  256. bool result = false;
  257. //建立连接
  258. string url = Host.TrimEnd('/') + RemotePath + fileName;
  259. FtpWebRequest request = CreateRequest(url, WebRequestMethods.Ftp.DeleteFile);
  260. using (FtpWebResponse response = (FtpWebResponse)request.GetResponse())
  261. {
  262. result = true;
  263. }
  264. return result;
  265. }
  266. #endregion
  267. #region 在FTP服务器上创建目录
  268. /// <summary>
  269. /// 在当前目录下创建文件夹
  270. /// </summary>
  271. /// <param name="dirName">文件夹名称</param>
  272. /// <returns>返回一个值,指示是否创建成功</returns>
  273. public bool MakeDirectory(string dirName)
  274. {
  275. bool result = false;
  276. //建立连接
  277. string url = Host.TrimEnd('/') + RemotePath + dirName;
  278. FtpWebRequest request = CreateRequest(url, WebRequestMethods.Ftp.MakeDirectory);
  279. using (FtpWebResponse response = (FtpWebResponse)request.GetResponse())
  280. {
  281. result = true;
  282. }
  283. return result;
  284. }
  285. #endregion
  286. #region 从FTP服务器上删除目录
  287. /// <summary>
  288. /// 删除文件夹
  289. /// </summary>
  290. /// <param name="dirName">文件夹名称</param>
  291. /// <returns>返回一个值,指示是否删除成功</returns>
  292. public bool DeleteDirectory(string dirName)
  293. {
  294. bool result = false;
  295. //建立连接
  296. string url = Host.TrimEnd('/') + RemotePath + dirName;
  297. FtpWebRequest request = CreateRequest(url, WebRequestMethods.Ftp.RemoveDirectory);
  298. using (FtpWebResponse response = (FtpWebResponse)request.GetResponse())
  299. {
  300. result = true;
  301. }
  302. return result;
  303. }
  304. #endregion
  305. #region 从FTP服务器上获取文件大小
  306. /// <summary>
  307. /// 获取文件大小
  308. /// </summary>
  309. /// <param name="fileName"></param>
  310. /// <returns></returns>
  311. public long GetFileSize(string fileName)
  312. {
  313. long result = 0;
  314. //建立连接
  315. string url = Host.TrimEnd('/') + RemotePath + fileName;
  316. FtpWebRequest request = CreateRequest(url, WebRequestMethods.Ftp.GetFileSize);
  317. using (FtpWebResponse response = (FtpWebResponse)request.GetResponse())
  318. {
  319. result = response.ContentLength;
  320. }
  321. return result;
  322. }
  323. #endregion
  324. #region 给FTP服务器上的文件追加内容
  325. /// <summary>
  326. /// 给FTP服务器上的文件追加内容
  327. /// </summary>
  328. /// <param name="localFile">本地文件</param>
  329. /// <param name="remoteFileName">FTP服务器上的文件</param>
  330. /// <returns>返回一个值,指示是否追加成功</returns>
  331. public bool Append(FileInfo localFile, string remoteFileName)
  332. {
  333. if (localFile.Exists)
  334. {
  335. using (FileStream fs = new FileStream(localFile.FullName, FileMode.Open))
  336. {
  337. return Append(fs, remoteFileName);
  338. }
  339. }
  340. throw new Exception(string.Format("本地文件不存在,文件路径:{0}", localFile.FullName));
  341. }
  342. /// <summary>
  343. /// 给FTP服务器上的文件追加内容
  344. /// </summary>
  345. /// <param name="stream">数据流(可通过设置偏移来实现从特定位置开始上传)</param>
  346. /// <param name="remoteFileName">FTP服务器上的文件</param>
  347. /// <returns>返回一个值,指示是否追加成功</returns>
  348. public bool Append(Stream stream, string remoteFileName)
  349. {
  350. bool result = false;
  351. if (stream != null && stream.CanRead)
  352. {
  353. //建立连接
  354. string url = Host.TrimEnd('/') + RemotePath + remoteFileName;
  355. FtpWebRequest request = CreateRequest(url, WebRequestMethods.Ftp.AppendFile);
  356. using (Stream rs = request.GetRequestStream())
  357. {
  358. //上传数据
  359. byte[] buffer = new byte[4096];//4K
  360. int count = stream.Read(buffer, 0, buffer.Length);
  361. while (count > 0)
  362. {
  363. rs.Write(buffer, 0, count);
  364. count = stream.Read(buffer, 0, buffer.Length);
  365. }
  366. result = true;
  367. }
  368. }
  369. return result;
  370. }
  371. #endregion
  372. #region 获取FTP服务器上的当前路径
  373. /// <summary>
  374. /// 获取FTP服务器上的当前路径
  375. /// </summary>
  376. public string CurrentDirectory
  377. {
  378. get
  379. {
  380. string result = string.Empty;
  381. string url = Host.TrimEnd('/') + RemotePath;
  382. FtpWebRequest request = CreateRequest(url, WebRequestMethods.Ftp.PrintWorkingDirectory);
  383. using (FtpWebResponse response = (FtpWebResponse)request.GetResponse())
  384. {
  385. string temp = response.StatusDescription;
  386. int start = temp.IndexOf('"') + 1;
  387. int end = temp.LastIndexOf('"');
  388. if (end >= start)
  389. {
  390. result = temp.Substring(start, end - start);
  391. }
  392. }
  393. return result;
  394. }
  395. }
  396. #endregion
  397. #region 检查当前路径上是否存在某个文件
  398. /// <summary>
  399. /// 检查文件是否存在
  400. /// </summary>
  401. /// <param name="fileName">要检查的文件名</param>
  402. /// <returns>返回一个值,指示要检查的文件是否存在</returns>
  403. public bool CheckFileExist(string fileName)
  404. {
  405. bool result = false;
  406. if (fileName != null && fileName.Trim().Length > 0)
  407. {
  408. fileName = fileName.Trim();
  409. List<string> files = GetFileList();
  410. if (files != null && files.Count > 0)
  411. {
  412. foreach (string file in files)
  413. {
  414. if (file.ToLower() == fileName.ToLower())
  415. {
  416. result = true;
  417. break;
  418. }
  419. }
  420. }
  421. }
  422. return result;
  423. }
  424. #endregion
  425. }
  426. }