該代碼主要實現,指定ftp服務地址,遍歷下載該地址下所有文件(含子文件夾下文件),並提供進度條顯示;另外附帶有通過http地址方式獲取服務器文件的簡單實例
廢話不多說,直接上代碼:
1、FTPHelper類
using System; using System.Collections.Generic; using System.IO; using System.Net; using System.Text; namespace FileBackup.FTP { /// <summary> /// FTP服務器文件處理 /// </summary> public class FTPHelper { private string _path; //ftp服務地址 private bool _isAuth; //是否需要身份驗證 private string _userName; //用戶名 private string _password; //密碼 public FTPHelper(string path, bool isAuth, string userName, string password) { _path = path; _isAuth = isAuth; _userName = userName; _password = password; } /// <summary> /// 獲取ftp路徑地址下文件/文件夾 /// </summary> /// <param name="relativePath">相對於ftp服務地址的路徑(相對路徑);不傳參則代表獲取ftp服務地址根目錄</param> /// <param name="isFloder">1、不傳參:獲取文件和文件夾;2、true:僅獲取文件夾;3、false:僅獲取文件</param> /// <returns></returns> public List<string> GetFileList(string relativePath = null, bool? isFloder = null) { List<string> result = new List<string>(); FtpWebRequest request; try { string path = _path; if (!string.IsNullOrEmpty(relativePath)) { path += relativePath; } request = (FtpWebRequest)FtpWebRequest.Create(new Uri(path)); request.UseBinary = true; //指定文件以二進制方式傳輸 //是否需要身份驗證 if (!_isAuth) { request.Credentials = new NetworkCredential(); } else { //設置用戶名和密碼 request.Credentials = new NetworkCredential(_userName, _password); } //設置ftp的命令 if (isFloder.HasValue) { //僅獲取列表 request.Method = WebRequestMethods.Ftp.ListDirectoryDetails; } else { //獲取詳情(僅獲取詳情時可以區分文件和文件夾) request.Method = WebRequestMethods.Ftp.ListDirectory; } WebResponse response = request.GetResponse(); StreamReader reader = new StreamReader(response.GetResponseStream()); string line = reader.ReadLine(); while (line != null) { //是否區分文件夾/文件讀取文件;若不區分,文件夾及文件會一起讀取 if (isFloder.HasValue) { //僅讀取文件夾 if ((bool)isFloder) { if (line.Contains("<DIR>")) { result.Add(line.Substring(line.LastIndexOf("<DIR>") + 5).Trim()); } } else { //讀取文件夾下文件 if (!line.Contains("<DIR>")) { result.Add(line.Substring(39).Trim()); } } } else { result.Add(line.Trim()); } //讀取下一行 line = reader.ReadLine(); } reader.Close(); response.Close(); return result; } catch (Exception ex) { Console.WriteLine("get the files/folders from the ftp:" + ex.Message); } return null; } /// <summary> /// 從FTP服務器下載文件,指定本地路徑和本地文件名(支持斷點下載) /// </summary> /// <param name="relativePath">遠程文件名</param> /// <param name="localFileName">保存本地的文件名(包含路徑)</param> /// <param name="size">已下載文件流大小</param> /// <param name="updateProgress">報告進度的處理(第一個參數:總大小,第二個參數:當前進度)</param> /// <returns>是否下載成功</returns> public bool FtpBrokenDownload(string relativePath, string localFileName, long size, Action<string, int, int, int> updateProgress = null, int? index = null) { FtpWebRequest reqFTP, ftpsize; Stream ftpStream = null; FtpWebResponse response = null; FileStream outputStream = null; try { string path = _path; if (!string.IsNullOrEmpty(relativePath)) { path += relativePath; } outputStream = new FileStream(localFileName, FileMode.Append); ftpsize = (FtpWebRequest)FtpWebRequest.Create(path); ftpsize.UseBinary = true; ftpsize.ContentOffset = size; reqFTP = (FtpWebRequest)FtpWebRequest.Create(path); reqFTP.UseBinary = true; reqFTP.KeepAlive = false; reqFTP.ContentOffset = size; if (_isAuth)//使用用戶身份認證 { ftpsize.Credentials = new NetworkCredential(_userName, _password); reqFTP.Credentials = new NetworkCredential(_userName, _password); } ftpsize.Method = WebRequestMethods.Ftp.GetFileSize; FtpWebResponse re = (FtpWebResponse)ftpsize.GetResponse(); long totalBytes = re.ContentLength; re.Close(); reqFTP.Method = WebRequestMethods.Ftp.DownloadFile; response = (FtpWebResponse)reqFTP.GetResponse(); ftpStream = response.GetResponseStream(); //更新進度 if (updateProgress != null) { updateProgress(localFileName.Substring(localFileName.LastIndexOf('\\') + 1, localFileName.Length - localFileName.LastIndexOf('\\') -1), (int)totalBytes, 0, (int)index);//更新進度條 } long totalDownloadedByte = 0; int bufferSize = 2048; int readCount; byte[] buffer = new byte[bufferSize]; readCount = ftpStream.Read(buffer, 0, bufferSize); while (readCount > 0) { totalDownloadedByte = readCount + totalDownloadedByte; outputStream.Write(buffer, 0, readCount); //更新進度 if (updateProgress != null) { updateProgress(localFileName.Substring(localFileName.LastIndexOf('\\') + 1, localFileName.Length - localFileName.LastIndexOf('\\') -1),(int)totalBytes, (int)totalDownloadedByte, (int)index);//更新進度條 } readCount = ftpStream.Read(buffer, 0, bufferSize); } ftpStream.Close(); outputStream.Close(); response.Close(); return true; } catch (Exception ex) { return false; throw; } finally { if (ftpStream != null) { ftpStream.Close(); } if (outputStream != null) { outputStream.Close(); } if (response != null) { response.Close(); } } } } }
2、HttpHelper類
using System; using System.Collections.Generic; using System.IO; using System.Net; using System.Text; namespace FileBackup.Http { public class HttpFileHelper { /// <summary> /// 文件下載(支持斷點續傳) /// </summary> /// <param name="httpPath"></param> /// <param name="saveFilePath"></param> /// <returns></returns> public bool DownLoadFiles(string httpPath, string saveFilePath) { bool flag = false; //打開上次下載的文件 long SPosition = 0; //實例化流對象 FileStream FStream; //判斷要下載的文件夾是否存在 if (File.Exists(saveFilePath)) { //打開要下載的文件 FStream = File.OpenWrite(saveFilePath); //獲取已經下載的長度 SPosition = FStream.Length; long serverFileLength = GetHttpLength(httpPath); //文件是完整的,直接結束下載任務 if (SPosition == serverFileLength) { return true; } FStream.Seek(SPosition, SeekOrigin.Current); } else { //文件不保存創建一個文件 FStream = new FileStream(saveFilePath, FileMode.Create); SPosition = 0; } try { //打開網絡連接 HttpWebRequest myRequest = (HttpWebRequest)HttpWebRequest.Create(httpPath); if (SPosition > 0) myRequest.AddRange((int)SPosition); //設置Range值 //向服務器請求,獲得服務器的回應數據流 Stream myStream = myRequest.GetResponse().GetResponseStream(); //定義一個字節數據 byte[] btContent = new byte[512]; int intSize = 0; intSize = myStream.Read(btContent, 0, 512); while (intSize > 0) { FStream.Write(btContent, 0, intSize); intSize = myStream.Read(btContent, 0, 512); } //關閉流 FStream.Close(); myStream.Close(); flag = true; } catch (Exception) { FStream.Close(); flag = false; } return flag; } /// <summary> /// 獲取http服務器端文件大小 /// </summary> /// <param name="url"></param> /// <returns></returns> private long GetHttpLength(string url) { long length = 0; try { var req = (HttpWebRequest)WebRequest.CreateDefault(new Uri(url)); req.Method = "HEAD"; req.Timeout = 5000; var res = (HttpWebResponse)req.GetResponse(); if (res.StatusCode == HttpStatusCode.OK) { length = res.ContentLength; } res.Close(); return length; } catch (WebException ex) { return 0; } } } }
3、測試類(Program.cs)
using System; using System.Collections.Generic; using System.ComponentModel; using System.IO; using System.Net; using FileBackup.Http; namespace FileBackup { class Program { //文件序號(遞增) static int index = 0; static void Main(string[] args) { Console.WriteLine("Loading........"); string path = "ftp://xxx.xxx.xxx.xxx:8765/"; //路徑結尾不需要帶斜杠 string localPath = @"E:\FTPTestFiles"; localPath = localPath.TrimEnd('\\'); //初始化ftp服務鏈接 FTPHelper fTPHelper = new FTPHelper(path, false, null, null); //獲取ftp根目錄下所有文件 List<string> fileList = fTPHelper.GetFileList(null, false); if (fileList != null) { //路徑不存在則創建 if (!Directory.Exists(localPath)) { Directory.CreateDirectory(localPath); } //下載文件到指定本地路徑 for (int i = 0; i < fileList.Count; i++) { Action<string, int, int, int> action = new Action<string, int, int, int>(ShowAction); index++; fTPHelper.FtpBrokenDownload(fileList[i], string.Format(@"{0}\{1}", localPath, fileList[i]), 0, action, index); } } //獲取ftp根目錄下所有文件夾 List<string> dirctoryList = fTPHelper.GetFileList(null, true); if (dirctoryList != null) { //遞歸下載文件夾下所有文件(初始父級相對路徑為空) FilesDownLoad(fTPHelper, dirctoryList, null, localPath); } //http文件下載測試 HttpFileHelper httpFileHelper = new HttpFileHelper(); httpFileHelper.DownLoadFiles("http://xxxxxxx:9798/upload/190125122251440.docx", string.Format(@"{0}\{1}", localPath, "httpfile.docx")); Console.WriteLine("End........"); Console.ReadLine(); } /// <summary> /// 下載文件夾列表下的所有文件(自動創建對應文件夾) /// </summary> /// <param name="fTPHelper"></param> /// <param name="dirctoryList">文件夾列表</param> /// <param name="parentRelativePath">ftp父級相對路徑</param> /// <param name="localPath">本地存放路徑</param> private static void FilesDownLoad(FTP.FTPHelper fTPHelper, List<string> dirctoryList, string parentRelativePath, string localPath) { if (dirctoryList != null) { for (int i = 0; i < dirctoryList.Count; i++) { //當前本地下載路徑 string localCurPath = string.Format(@"{0}\{1}", localPath, dirctoryList[i]); ; //當前ftp相對路徑 string ftpCurPath = dirctoryList[i]; if (!string.IsNullOrEmpty(parentRelativePath)) { ftpCurPath = string.Format(@"{0}\{1}", parentRelativePath, dirctoryList[i]); } //路徑不存在則創建 if (!Directory.Exists(localCurPath)) { Directory.CreateDirectory(localCurPath); } //獲取文件夾下所有文件 List<string> subfileList = fTPHelper.GetFileList(ftpCurPath, false); if(subfileList != null) { for (int j = 0; j < subfileList.Count; j++) { //下載文件夾下所有文件,文件名與ftp服務器上文件名保持一致(含后綴) Action<string, int, int, int> action = new Action<string, int, int, int>(ShowAction); index++; fTPHelper.FtpBrokenDownload(string.Format(@"{0}\{1}", ftpCurPath, subfileList[j]), string.Format(@"{0}\{1}", localCurPath, subfileList[j]), 0, action, index); } } //獲取該文件夾下所有子文件夾 List<string> subdirctoryList = fTPHelper.GetFileList(ftpCurPath, true); if (subdirctoryList != null) { //遞歸下載文件夾下所有文件 FilesDownLoad(fTPHelper, subdirctoryList, ftpCurPath, localCurPath); } } } } /// <summary> /// 控制台進度顯示 /// </summary> /// <param name="file"></param> /// <param name="size"></param> /// <param name="progress"></param> /// <param name="rowIndex"></param> public static void ShowAction(string file, int size, int progress, int rowIndex) { //命令行光標位置定位 Console.SetCursorPosition(0, rowIndex); if (size > 0) { Console.WriteLine(string.Format("{0}: Total Size:{1}; Progress:{2}%", file, size, Math.Round((Double)progress*100 / (Double)size, 0))); } else { Console.WriteLine(string.Format("{0}: Total Size:{1}; Progress:{2}%", file, size, 100)); } } } }