using System; using System.Net; using System.Net.Sockets; using System.Text; using System.IO; using System.Collections; using System.Collections.Generic; using System.Text.RegularExpressions; using System.Globalization; namespace UpdateSys.Common { /// <summary> /// ftp文件上传、下载操作类 /// </summary> public class FTPHelper { /// <summary> /// ftp用户名,匿名为“” /// </summary> private string ftpUser; /// <summary> /// ftp用户密码,匿名为“” /// </summary> private string ftpPassWord; /// <summary> ///通过用户名,密码连接到FTP服务器 /// </summary> /// <param name="ftpUser">ftp用户名,匿名为“”</param> /// <param name="ftpPassWord">ftp登陆密码,匿名为“”</param> public FTPHelper(string ftpUser, string ftpPassWord) { this.ftpUser = ftpUser; this.ftpPassWord = ftpPassWord; } /// <summary> /// 匿名访问 /// </summary> public FTPHelper() { this.ftpUser = ""; this.ftpPassWord = ""; } /// <summary> /// 上传文件到Ftp服务器,如果ftp服务器存在名称相同的文件,会覆盖ftp原来的文件 /// </summary> /// <param name="uri">把上传的文件保存为ftp服务器文件的uri,如"ftp://192.168.1.104/capture-212.avi"</param> /// <param name="upLoadFile">要上传的本地的文件路径,如D:capture-2.avi</param> public void UpLoadFile(string UpLoadUri, string upLoadFile) { Stream requestStream = null; FileStream fileStream = null; FtpWebResponse uploadResponse = null; try { Uri uri = new Uri(UpLoadUri); FtpWebRequest uploadRequest = (FtpWebRequest)WebRequest.Create(uri); uploadRequest.Method = WebRequestMethods.Ftp.UploadFile; uploadRequest.Credentials = new NetworkCredential(ftpUser, ftpPassWord); requestStream = uploadRequest.GetRequestStream(); fileStream = File.Open(upLoadFile, FileMode.Open); byte[] buffer = new byte[1024]; int bytesRead; while (true) { bytesRead = fileStream.Read(buffer, 0, buffer.Length); if (bytesRead == 0) break; requestStream.Write(buffer, 0, bytesRead); } requestStream.Close(); uploadResponse = (FtpWebResponse)uploadRequest.GetResponse(); } catch (Exception ex) { throw new Exception("上传文件到ftp服务器出错,文件名:" + upLoadFile + "异常信息:" + ex.ToString()); } finally { if (uploadResponse != null) uploadResponse.Close(); if (fileStream != null) fileStream.Close(); if (requestStream != null) requestStream.Close(); } } /// <summary> /// 上传文件到ftp服务器,如果ftp服务器上存在同名文件,文件会被覆盖 /// /// </summary> /// <param name="ftpDir"></param> /// <param name="subDir"></param> /// <param name="fileName"></param> /// <param name="upLoadFile"></param> public void UpLoadFile(string ftpDir,string subDir,string fileName, string upLoadFile) { Stream requestStream = null; FileStream fileStream = null; FtpWebResponse uploadResponse = null; try { //如果子目录不存在,新建目录 if (!DirectoryExist(ftpDir, subDir)) { MakeDirectory(ftpDir+"/"+subDir); } Uri uri = new Uri(ftpDir+"/"+subDir+"/"+fileName); FtpWebRequest uploadRequest = (FtpWebRequest)WebRequest.Create(uri); uploadRequest.Method = WebRequestMethods.Ftp.UploadFile; uploadRequest.Credentials = new NetworkCredential(ftpUser, ftpPassWord); requestStream = uploadRequest.GetRequestStream(); fileStream = File.Open(upLoadFile, FileMode.Open); byte[] buffer = new byte[1024]; int bytesRead; while (true) { bytesRead = fileStream.Read(buffer, 0, buffer.Length); if (bytesRead == 0) break; requestStream.Write(buffer, 0, bytesRead); } requestStream.Close(); uploadResponse = (FtpWebResponse)uploadRequest.GetResponse(); } catch (Exception ex) { throw new Exception("上传文件到ftp服务器出错,文件名:" + upLoadFile + "异常信息:" + ex.ToString()); } finally { if (uploadResponse != null) uploadResponse.Close(); if (fileStream != null) fileStream.Close(); if (requestStream != null) requestStream.Close(); } } /// <summary> /// 从ftp下载文件到本地服务器 /// </summary> /// <param name="downloadUrl">要下载的ftp文件路径,如ftp://192.168.1.104/capture-2.avi</param> /// <param name="saveFileUrl">本地保存文件的路径,如(@"d:capture-22.avi"</param> public void DownLoadFile(string downloadUrl, string saveFileUrl) { Stream responseStream = null; FileStream fileStream = null; StreamReader reader = null; try { // string downloadUrl = "ftp://192.168.1.104/capture-2.avi"; FtpWebRequest downloadRequest = (FtpWebRequest)WebRequest.Create(downloadUrl); downloadRequest.Method = WebRequestMethods.Ftp.DownloadFile; //string ftpUser = "yoyo"; //string ftpPassWord = "123456"; downloadRequest.Credentials = new NetworkCredential(ftpUser, ftpPassWord); FtpWebResponse downloadResponse = (FtpWebResponse)downloadRequest.GetResponse(); responseStream = downloadResponse.GetResponseStream(); fileStream = File.Create(saveFileUrl); byte[] buffer = new byte[1024]; int bytesRead; while (true) { bytesRead = responseStream.Read(buffer, 0, buffer.Length); if (bytesRead == 0) break; fileStream.Write(buffer, 0, bytesRead); } } catch (Exception ex) { throw new Exception("从ftp服务器下载文件出错,文件名:" + downloadUrl + "异常信息:" + ex.ToString()); } finally { if (reader != null) { reader.Close(); } if (responseStream != null) { responseStream.Close(); } if (fileStream != null) { fileStream.Close(); } } } /// <summary> /// 从FTP下载文件到本地服务器,支持断点下载。实现文件夹级别的断点,而不是文件级的断点。 /// 文件下载完成后,把本地文件的最后修改时间设置成FTP的文件最后修改时间 /// 下次下载的时候,如果文件的最后修改时间相同,断点下载;如果最后修改时间不相同,重新下载该文件 /// </summary> /// <param name="ftpUri">ftp文件路径,如"ftp://localhost/test.txt"</param> /// <param name="saveFile">保存文件的路径,如C:\test.txt</param> public void BreakPointDownLoadFile(string ftpUri, string saveFile) { System.IO.FileStream fs = null; System.Net.FtpWebResponse ftpRes = null; System.IO.Stream resStrm = null; try { //下载文件的URI Uri u = new Uri(ftpUri); //设定下载文件的保存路径 string downFile = saveFile; //FtpWebRequest的作成 System.Net.FtpWebRequest ftpReq = (System.Net.FtpWebRequest) System.Net.WebRequest.Create(u); //设定用户名和密码 ftpReq.Credentials = new System.Net.NetworkCredential(ftpUser, ftpPassWord); //MethodにWebRequestMethods.Ftp.DownloadFile("RETR")设定 ftpReq.Method = System.Net.WebRequestMethods.Ftp.DownloadFile; //要求终了后不关闭连接 ftpReq.KeepAlive = true; //使用ASCII方式传送 ftpReq.UseBinary = false; //设定PASSIVE方式无效 ftpReq.UsePassive = false; //判断是否继续下载 //继续写入下载文件的FileStream //if (System.IO.File.Exists(downFile)) if (FileExistAndLastModify(ftpUri,downFile)) { //继续下载 ftpReq.ContentOffset = (new System.IO.FileInfo(downFile)).Length; fs = new System.IO.FileStream( downFile, System.IO.FileMode.Append, System.IO.FileAccess.Write); } else { //一般下载 fs = new System.IO.FileStream( downFile, System.IO.FileMode.Create, System.IO.FileAccess.Write); } //取得FtpWebResponse ftpRes = (System.Net.FtpWebResponse)ftpReq.GetResponse(); //为了下载文件取得Stream resStrm = ftpRes.GetResponseStream(); //写入下载的数据 byte[] buffer = new byte[1024]; while (true) { int readSize = resStrm.Read(buffer, 0, buffer.Length); if (readSize == 0) break; fs.Write(buffer, 0, readSize); } //下载完成,设置本地保存文件的最后修改时间=ftp文件的最后修改时间 fs.Close(); SetLastModifySame(ftpUri,downFile); } catch (Exception ex) { throw new Exception("从ftp服务器下载文件出错,文件名:" + ftpUri + "异常信息:" + ex.ToString()); } finally { if (fs != null) { fs.Close(); } if (resStrm != null) { resStrm.Close(); } if (ftpRes != null) { ftpRes.Close(); } } } /// <summary> /// 判断本地文件是否存在,并且最后修改时间和ftp文件是否相同,如果文件存在,最后修改时间相同,断点下载 /// </summary> /// <param name="ftpUri">FTP路径</param> /// <param name="saveFile">文件保存路径,绝对目录</param> /// <returns></returns> private bool FileExistAndLastModify(string ftpUri, string saveFile) { if (!File.Exists(saveFile)) { return false; } FileInfo file = new FileInfo(saveFile); DateTime ftpFileModifyDate = GetLastModifyDate(ftpUri); DateTime saveFileModifyDate = file.LastWriteTime; if (ftpFileModifyDate != saveFileModifyDate) { return false; } return true; } /// <summary> /// 设置本地保存文件的最后修改时间=ftp最后修改时间 /// </summary> /// <param name="ftpUri"></param> /// <param name="saveFile"></param> private void SetLastModifySame(string ftpUri,string saveFile) { FileInfo file = new FileInfo(saveFile); DateTime ftpFileModifyDate = GetLastModifyDate(ftpUri); file.LastWriteTime = ftpFileModifyDate; } #region 从FTP上下载整个文件夹,包括文件夹下的文件和文件夹 /// <summary> /// 列出FTP服务器上面当前目录的所有文件和目录 /// </summary> /// <param name="ftpUri">FTP目录</param> /// <returns></returns> public List<FileStruct> ListFilesAndDirectories(string ftpUri) { WebResponse webresp = null; StreamReader ftpFileListReader = null; FtpWebRequest ftpRequest = null; try { ftpRequest = (FtpWebRequest)WebRequest.Create(new Uri(ftpUri)); ftpRequest.Method = WebRequestMethods.Ftp.ListDirectoryDetails; ftpRequest.Credentials = new NetworkCredential(ftpUser, ftpPassWord); webresp = ftpRequest.GetResponse(); ftpFileListReader = new StreamReader(webresp.GetResponseStream(), Encoding.Default); } catch (Exception ex) { throw new Exception("获取文件列表出错,错误信息如下:"+ex.ToString()); } string Datastring = ftpFileListReader.ReadToEnd(); return GetList(Datastring); } /// <summary> /// 列出FTP目录下的所有文件 /// </summary> /// <param name="ftpUri">FTP目录</param> /// <returns></returns> public List<FileStruct> ListFiles(string ftpUri) { List<FileStruct> listAll = ListFilesAndDirectories(ftpUri); List<FileStruct> listFile = new List<FileStruct>(); foreach (FileStruct file in listAll) { if (!file.IsDirectory) { listFile.Add(file); } } return listFile; } /// <summary> /// 列出FTP目录下的所有目录 /// </summary> /// <param name="ftpUri">FRTP目录</param> /// <returns>目录列表</returns> public List<FileStruct> ListDirectories(string ftpUri) { List<FileStruct> listAll = ListFilesAndDirectories(ftpUri); List<FileStruct> listDirectory = new List<FileStruct>(); foreach (FileStruct file in listAll) { if (file.IsDirectory) { listDirectory.Add(file); } } return listDirectory; } /// <summary> /// 获得文件和目录列表 /// </summary> /// <param name="datastring">FTP返回的列表字符信息</param> private List<FileStruct> GetList(string datastring) { List<FileStruct> myListArray = new List<FileStruct>(); string[] dataRecords = datastring.Split(' '); FileListStyle _directoryListStyle = GuessFileListStyle(dataRecords); foreach (string s in dataRecords) { if (_directoryListStyle != FileListStyle.Unknown && s != "") { FileStruct f = new FileStruct(); f.Name = ".."; switch (_directoryListStyle) { case FileListStyle.UnixStyle: f = ParseFileStructFromUnixStyleRecord(s); break; case FileListStyle.WindowsStyle: f = ParseFileStructFromWindowsStyleRecord(s); break; } if (!(f.Name == "." || f.Name == "..")) { myListArray.Add(f); } } } return myListArray; } /// <summary> /// 从Unix格式中返回文件信息 /// </summary> /// <param name="Record">文件信息</param> private FileStruct ParseFileStructFromUnixStyleRecord(string Record) { FileStruct f = new FileStruct(); string processstr = Record.Trim(); f.Flags = processstr.Substring(0, 10); f.IsDirectory = (f.Flags[0] == 'd'); processstr = (processstr.Substring(11)).Trim(); _cutSubstringFromStringWithTrim(ref processstr, ' ', 0); //跳过一部分 f.Owner = _cutSubstringFromStringWithTrim(ref processstr, ' ', 0); f.Group = _cutSubstringFromStringWithTrim(ref processstr, ' ', 0); _cutSubstringFromStringWithTrim(ref processstr, ' ', 0); //跳过一部分 string yearOrTime = processstr.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)[2]; if (yearOrTime.IndexOf(":") >= 0) //time { processstr = processstr.Replace(yearOrTime, DateTime.Now.Year.ToString()); } f.CreateTime = DateTime.Parse(_cutSubstringFromStringWithTrim(ref processstr, ' ', 8)); f.Name = processstr; //最后就是名称 return f; } /// <summary> /// 从Windows格式中返回文件信息 /// </summary> /// <param name="Record">文件信息</param> private FileStruct ParseFileStructFromWindowsStyleRecord(string Record) { FileStruct f = new FileStruct(); string processstr = Record.Trim(); string dateStr = processstr.Substring(0, 8); processstr = (processstr.Substring(8, processstr.Length - 8)).Trim(); string timeStr = processstr.Substring(0, 7); processstr = (processstr.Substring(7, processstr.Length - 7)).Trim(); DateTimeFormatInfo myDTFI = new CultureInfo("en-US", false).DateTimeFormat; myDTFI.ShortTimePattern = "t"; f.CreateTime = DateTime.Parse(dateStr + " " + timeStr, myDTFI); if (processstr.Substring(0, 5) == "<DIR>") { f.IsDirectory = true; processstr = (processstr.Substring(5, processstr.Length - 5)).Trim(); } else { string[] strs = processstr.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); // true); processstr = strs[1]; f.IsDirectory = false; } f.Name = processstr; return f; } /// <summary> /// 按照一定的规则进行字符串截取 /// </summary> /// <param name="s">截取的字符串</param> /// <param name="c">查找的字符</param> /// <param name="startIndex">查找的位置</param> private string _cutSubstringFromStringWithTrim(ref string s, char c, int startIndex) { int pos1 = s.IndexOf(c, startIndex); string retString = s.Substring(0, pos1); s = (s.Substring(pos1)).Trim(); return retString; } /// <summary> /// 判断文件列表的方式Window方式还是Unix方式 /// </summary> /// <param name="recordList">文件信息列表</param> private FileListStyle GuessFileListStyle(string[] recordList) { foreach (string s in recordList) { if (s.Length > 10 && Regex.IsMatch(s.Substring(0, 10), "(-|d)(-|r)(-|w)(-|x)(-|r)(-|w)(-|x)(-|r)(-|w)(-|x)")) { return FileListStyle.UnixStyle; } else if (s.Length > 8 && Regex.IsMatch(s.Substring(0, 8), "[0-9][0-9]-[0-9][0-9]-[0-9][0-9]")) { return FileListStyle.WindowsStyle; } } return FileListStyle.Unknown; } /// <summary> /// 从FTP下载整个文件夹 /// </summary> /// <param name="ftpDir">FTP文件夹路径</param> /// <param name="saveDir">保存的本地文件夹路径</param> public void DownFtpDir(string ftpDir, string saveDir) { List<FileStruct> files = ListFilesAndDirectories(ftpDir); if (!Directory.Exists(saveDir)) { Directory.CreateDirectory(saveDir); } foreach (FileStruct f in files) { if (f.IsDirectory) //文件夹,递归查询 { DownFtpDir(ftpDir + "/" + f.Name, saveDir + "\" + f.Name); } else //文件,直接下载 { BreakPointDownLoadFile(ftpDir + "/" + f.Name, saveDir + "\" + f.Name); } } } /// <summary> /// 上传整个文件夹的文件到ftp 服务器 /// </summary> /// <param name="localDir">本地文件夹</param> /// <param name="ftpDir">ftp文件夹</param> public void UpLoadDirToFtpServer(string localDir, string ftpDir) { if (!Directory.Exists(localDir)) { throw new Exception("上传文件夹:" + localDir + "出错,因为" + localDir + "不存在!"); } DirectoryInfo localDirInfo = new DirectoryInfo(localDir); FileInfo[] files = localDirInfo.GetFiles(); for (int i = 0; i < files.Length; i++) { UpLoadFile(ftpDir + "/" + files[i].Name, files[i].FullName); } DirectoryInfo[] dirs = localDirInfo.GetDirectories(); for (int j = 0; j < dirs.Length; j++) { //如果子目录不存在,新建目录 if (!DirectoryExist(ftpDir, dirs[j].Name)) { MakeDirectory(ftpDir + "/" + dirs[j].Name); } UpLoadDirToFtpServer(dirs[j].FullName, ftpDir + "/" + dirs[j].Name); } } #endregion /// <summary> /// 获取ftp服务器文件的最后修改时间 /// </summary> /// <param name="ftpFileUri">ftp文件的完整路径,如ftp://192.168.1.104/abcd.txt</param> /// <returns></returns> public DateTime GetLastModifyDate(string ftpFileUri) { DateTime LastModifieDate = new DateTime(); FtpWebResponse uploadResponse = null; try { Uri uri = new Uri(ftpFileUri); FtpWebRequest uploadRequest = (FtpWebRequest)WebRequest.Create(uri); uploadRequest.Method = WebRequestMethods.Ftp.GetDateTimestamp; uploadRequest.Credentials = new NetworkCredential(ftpUser, ftpPassWord); uploadResponse = (FtpWebResponse)uploadRequest.GetResponse(); LastModifieDate = uploadResponse.LastModified; return LastModifieDate; } catch (Exception ex) { throw ex; } finally { if (uploadResponse != null) uploadResponse.Close(); } } /// <summary> /// 把ftp上的文件移动到ftp的另外一个目录 /// </summary> /// <param name="ftpFileUri">ftp文件路径</param> /// <param name="ftpDir">文件移动到的ftp目录</param> /// <param name="deleteFile">移动后是否删除原文件</param> public void MoveFileToOtherDir(string ftpFileUri, string ftpDir,bool deleteFile) { } /// <summary> /// /// </summary> /// <param name="ftpFileUri"></param> public void DeleteFile(string ftpFileUri) { FtpWebResponse Response = null; try { Uri uri = new Uri(ftpFileUri); FtpWebRequest Request = (FtpWebRequest)WebRequest.Create(uri); Request.Method = WebRequestMethods.Ftp.DeleteFile; Request.Credentials = new NetworkCredential(ftpUser, ftpPassWord); // requestStream = Request.GetRequestStream(); Response = (FtpWebResponse)Request.GetResponse(); } catch (Exception ex) { throw new Exception("从ftp删除文件出错,文件名:" + ftpFileUri + "异常信息:" + ex.ToString()); } finally { if (Response != null) Response.Close(); } } /// <summary> /// 判断ftp指定目录下是否存在子目录 /// </summary> /// <param name="ftpDir">ftp目录</param> /// <param name="RemoteDirectoryName">子目录名称</param> /// <returns></returns> public bool DirectoryExist(string ftpDir, string RemoteDirectoryName) { List<FileStruct> dirs = ListDirectories(ftpDir); foreach (FileStruct dir in dirs) { if (RemoteDirectoryName == dir.Name) { return true; } } return false; } /// <summary> /// 判断一个远程文件是否存在服务器当前目录下面 /// </summary> /// <param name="RemoteDir">远程目录</param> /// <param name="FileName">远程文件名称</param> public bool FileExist(string RemoteDir,string FileName) { List<FileStruct> files = ListFiles(RemoteDir); foreach (FileStruct file in files) { if (FileName == file.Name) { return true; } } return false; } /// <summary> /// 新建目录 /// </summary> /// <param name="dir"></param> public void MakeDirectory(string dir) { FtpWebResponse Response = null; try { Uri uri = new Uri(dir); FtpWebRequest Request = (FtpWebRequest)WebRequest.Create(uri); Request.Method = WebRequestMethods.Ftp.MakeDirectory; Request.Credentials = new NetworkCredential(ftpUser, ftpPassWord); // requestStream = Request.GetRequestStream(); Response = (FtpWebResponse)Request.GetResponse(); } catch (Exception ex) { throw new Exception("新建目录出错,目录:" + dir + "异常信息:" + ex.ToString()); } finally { if (Response != null) Response.Close(); } } } #region 文件信息结构 public struct FileStruct { public string Flags; public string Owner; public string Group; public bool IsDirectory; public DateTime CreateTime; public string Name; } public enum FileListStyle { UnixStyle, WindowsStyle, Unknown } #endregion } 下载整个文件夹,调用如下: FTPHelper FTP = new FTPHelper("userName", "passWord"); FTP.DownFtpDir("ftp://192.168.1.104/", "F:\test");