前段时间做了一个FTP操作服务器文件的实验,现在把一些经验写下来,免得忘记。
1、上传的处理:目标文件夹A上传到服务器指定目录。先检索服务器目录中有无同名文件夹,若有,则先改名,上传成功后再删除,上传失败则回复文件夹名。
1)、检查文件夹是否存在
/// <summary> /// 检查文件夹在服务器上是否已存在 /// </summary> /// <param name="path"></param> /// <returns></returns> private static bool CheckExist(string fileName) { FtpWebRequest checkRequest = (FtpWebRequest)FtpWebRequest.Create(new Uri(_upLoadPath)); checkRequest.Method = WebRequestMethods.Ftp.ListDirectory; checkRequest.UseBinary = true; checkRequest.Credentials = new NetworkCredential(_userName, _password); FtpWebResponse response = (FtpWebResponse)checkRequest.GetResponse(); StreamReader sw = new StreamReader(response.GetResponseStream()); List<string> files = new List<string>(); string line = sw.ReadLine(); while (line != null) { files.Add(line.Substring(line.IndexOf("/") + 1)); line = sw.ReadLine(); } sw.Close(); response.Close(); return files.Contains(fileName); }
2)、文件夹的重命名
/// <summary> /// 文件夹重命名 /// </summary> /// <param name="oldName"></param> /// <param name="newName"></param> private static void RenameFolder(string oldName, string newName) { string uri = _upLoadPath + "/" + oldName; FtpWebRequest ftpRequest = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri)); ftpRequest.Method = WebRequestMethods.Ftp.Rename; ftpRequest.UseBinary = true; ftpRequest.Credentials = new NetworkCredential(_userName, _password); ftpRequest.RenameTo = newName; FtpWebResponse ftpResponse = (FtpWebResponse)ftpRequest.GetResponse(); ftpResponse.Close(); }
3)、文件夹的上传
/// <summary> /// 上传文件夹 /// </summary> /// <param name="folderInfo">待上传文件夹的信息</param> private static void UpLoadFolder(DirectoryInfo folderInfo) { // 服务器上文件夹的位置为根目录加上相对位置 // rootPath = (new DirectoryInfo(_localPath)).Parent.FullName; rootPath是待上传文件夹的目录 string foldePath = folderInfo.FullName.Substring(rootPath.Length).Replace(‘\\‘, ‘/‘); string uriPath = _upLoadPath + "/" + foldePath; // 创建文件夹 CreateFolder(uriPath); // 递归创建子文件夹并上传文件 if (folderInfo != null) { foreach (DirectoryInfo folder in folderInfo.GetDirectories()) { UpLoadFolder(folder); } foreach (FileInfo file in folderInfo.GetFiles()) { UpLoadFile(file); } } }
/// <summary> /// 创建文件夹 /// </summary> /// <param name="folderPath">文件夹路径</param> private static void CreateFolder(string folderPath) { FtpWebRequest request = (FtpWebRequest)FtpWebRequest.Create(new Uri(uriPath)); request.Method = WebRequestMethods.Ftp.MakeDirectory; request.UseBinary = true; request.Credentials = new NetworkCredential(_userName, _password); FtpWebResponse response = (FtpWebResponse)request.GetResponse(); Stream ftpStream = response.GetResponseStream(); ftpStream.Close(); response.Close(); }
/// <summary> /// 上传单个文件 /// </summary> /// <param name="file"></param> private static void UpLoadFile(FileInfo file) { // 服务器上文件的位置为根目录加上相对位置 string fileName = file.FullName.Substring(rootPath.Length).Replace(‘\\‘, ‘/‘); string uriPath = _upLoadPath + "/" + fileName; FtpWebRequest request = (FtpWebRequest)FtpWebRequest.Create(new Uri(uriPath)); request.Method = WebRequestMethods.Ftp.UploadFile; request.Credentials = new NetworkCredential(_userName, _password); FtpWebResponse upLoadResponse = (FtpWebResponse)request.GetResponse(); Stream upLoadStream = request.GetRequestStream(); using (FileStream fileStream = File.Open(file.FullName, FileMode.Open)) { byte[] buffer = new byte[1024]; int bytesRead; while (true) { bytesRead = fileStream.Read(buffer, 0, buffer.Length); if (bytesRead == 0) break; upLoadStream.Write(buffer, 0, bytesRead); } } upLoadStream.Close(); upLoadResponse.Close(); }
4)、文件夹的删除
/// <summary> /// 删除文件夹及子文件和子文件夹 /// </summary> /// <param name="folderName"></param> private static void DeleteFolder(string folderName) { string uri = _upLoadPath + "/" + folderName; FtpWebRequest searchRequest = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri)); searchRequest.Method = WebRequestMethods.Ftp.ListDirectoryDetails; searchRequest.Credentials = new NetworkCredential(_userName, _password); FtpWebResponse searchResponse = (FtpWebResponse)searchRequest.GetResponse(); StreamReader sw = new StreamReader(searchResponse.GetResponseStream()); List<string> files = new List<string>(); List<string> folders = new List<string>(); string line = sw.ReadLine(); while (line != null) { // windows下的文件夹读取到的数据以“d”开头,以“空格” + 文件夹名 结束 if (line.StartsWith("d")) folders.Add(line.Substring(line.LastIndexOf(" ") + 1)); else files.Add(line.Substring(line.LastIndexOf(" ") + 1)); line = sw.ReadLine(); } sw.Close(); searchResponse.Close(); // 递归删除服务器上的文件夹和文件 foreach (string folder in folders) { DeleteFolder(folderName + "/" + folder); } foreach (string file in files) { DeleteFile(folderName + "/" + file); } FtpWebRequest deleteRequest = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri)); deleteRequest.Method = WebRequestMethods.Ftp.RemoveDirectory; deleteRequest.Credentials = new NetworkCredential(_userName, _password); FtpWebResponse deleteResponse = (FtpWebResponse)deleteRequest.GetResponse(); deleteResponse.Close(); }
/// <summary> /// 删除单个文件 /// </summary> /// <param name="fileName"></param> private static void DeleteFile(string fileName) { string uri = _upLoadPath + "/" + fileName; FtpWebRequest deleteRequest = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri)); deleteRequest.Method = WebRequestMethods.Ftp.DeleteFile; deleteRequest.Credentials = new NetworkCredential(_userName, _password); FtpWebResponse deleteResponse = (FtpWebResponse)deleteRequest.GetResponse(); deleteResponse.Close(); }
至此,上传算是完成了。一些异常处理,配置文件的格式就不贴出来了。
2)、下载,一样是重命名,下载,删除的套路。但重命名和删除是在本地,很容易实现。而FTP下载的代码也与上传代码非常镜像,递归创建子文件夹和读取写文件就好了。
总结:对于ftp服务器上文件的任何操作
1.都需要用Uri(包含IP、端口号和目录的完整路径)去实例化一个FtpWebRequest对象。
2.用FtpWebRequest对象的Method属性来选择操作文件的方式,本文出现了ListDirectory(获取子文件夹信息)、Rename、MakeDirectory(创建文件夹)、UploadFile、ListDirectoryDetails(获取子文件夹及文件信息)、RemoveDirectory、DeleteFile以及文中没有出现但下载需用到的DownloadFile。
3.连接FTP服务器XXXXRequest.Credentials = new NetworkCredential(_userName, _password)
4.得到FTP的响应对象FtpWebResponse
5.如有必要,可获得响应对象FtpWebResponse的流GetRequestStream(),并进行读写操作。
可以看到FTP各种操作的相关代码非常类似,容易看懂,功能清晰。通过这次实验,接触了FTP服务器的搭建(FileZilla Server Interface工具一路点下一步。。。),学习了C#怎么实现FTP的上传下载,怎么用C#写windows服务以及如何调试(这个有时间、有闲心的话,也写一下,贡以后自己参考吧)。