C#的FTP上传下载的实验

前段时间做了一个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(获取子文件夹信息)、RenameMakeDirectory(创建文件夹)、UploadFileListDirectoryDetails(获取子文件夹及文件信息)、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服务以及如何调试(这个有时间、有闲心的话,也写一下,贡以后自己参考吧)。

C#的FTP上传下载的实验

上一篇:C# 除法的细节


下一篇:关于TF(词频) 和TF-IDF(词频-逆向文件频率 )的理解