通过ftp同步服务器文件:遍历文件夹所有文件(含子文件夹、进度条);简单http同步服务器文件实例
该代码主要实现,指定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)); } } } }