文件传输协议 (FTP) 是一个标准协议,可用来通过 Internet 将文件从一台计算机移到另一台计算机。 这些文件存储在运行 FTP 服务器软件的服务器计算机上。 然后,远程计算机可以使用 FTP 建立连接,并从服务器读取文件或将文件复制到服务器。 FTP 服务器与 HTTP 服务器(即 Web 服务器)的相似之处在于可以使用 Internet 协议与之通信。 但是,FTP 服务器不运行网页;它只是向/从远程计算机发送/接收文件。
可以将 Internet 信息服务 (IIS) 配置为作为 FTP 服务器来运行。 这样,其他计算机便可以连接到服务器并将文件复制到服务器或者从服务器复制文件。 例如,如果您在自己的计算机上承载网站,并且希望允许远程用户连接到您的计算机并将他们的文件复制到服务器,则可以将 IIS 配置为充当 FTP 服务器。
本文主要讲解一下,在Window的IIS中创建FTP的Site并用C#进行文件的上传下载。
1): 首先展示一下我的Window环境
2): 在配置环境之前,我们要保证相应的Window的feature都已经开启了,如下图所示
3): 打开我们的IIS Manager,在Sites的节点点击鼠标右键,选择Add FTP Site
4): 接上图,之后会出现如下视图,我们可以填写对应的 FTP site name,然后选择本地某一个磁盘的folder作为此 FTP site 的 Physical path
5): 填写好必要的信息之后,我们点击 Next 进入如下界面,可以看出FTP对应的端口号位21,我们这里选择了Allow SSL就是对传输的内容进行加密【即:所谓的SFTP,但是依旧使用的是FTP协议,这与http和https的关系不完全类似】
【注:引文---我们都知道FTP对应的端口应该是21,为什么又冒出来一个20呢?其实,我们们进行FTP文件传输中,客户端首先连接到FTP服务器的21端口,进行用户的认证,认证成功后,当我们要传输文件时,服务器会开一个端口为20来进行传输数据文件,也就是说,端口20才是真正传输所用到的端口,端口21只用于FTP的登陆认证。我们平常下载文件时,会遇到下载到99%时,文件不完成,不能成功的下载。其实是因为文件下载完毕后,还要在21端口再行进行用户认证,而我们下载文件的时间如果过长,客户机与服务器的21端口的连接会被服务器认为是超时连接而中断掉,就是这个原因。解决方法就是设置21端口的响应时间。】
6): 接上图,点击Next按钮之后,我们将EricSun_FTP这个用户赋予对应的权限,之后的程序中我们也用此用户的信息进行登录认证
7): 上面的步骤都设置完之后,我们用 ftp://192.168.181.133 【当然了这里要换成你自己环境的 ip 地址】来访问,会直接映射到我们之前设置的物理地址 E盘的 FTP 文件夹
【如果是第一次访问的话,会弹出一个界面让你输入用户名和密码进行认证,这里省略】
【【 更加官方的配置过程我们可以访问此链接:http://msdn.microsoft.com/zh-cn/library/6ws081sa(v=vs.100).aspx 】】
8): 配置好了这样的一个 FTP site之后,可以用如下C#代码进行访问来处理文件的上传和下载
public static void DownloadByFtp(string uri, MemoryStream stream, bool isInternalAuth, string sftpUserName, string sftpPassword) { if (!uri.Contains("ftp://")) uri = "ftp://" + uri; FtpWebRequest request = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri)); if (!isInternalAuth) request.Credentials = new NetworkCredential(sftpUserName, sftpPassword); request.KeepAlive = false; request.Method = WebRequestMethods.Ftp.DownloadFile; request.UseBinary = true; FtpWebResponse response = (FtpWebResponse)request.GetResponse(); Stream responseStream = response.GetResponseStream(); int len = 0; do { byte[] buffer = new byte[2048]; len = responseStream.Read(buffer, 0, buffer.Length); stream.Write(buffer, 0, len); } while (len > 0); responseStream.Close(); response.Close(); stream.Position = 0; } public static void UploadByFtp(string ftpAddress, MemoryStream fileStream, string folderName, string fileName, string sftpUsername, string sftpPassword) { string uri = string.Empty; if (ftpAddress.Contains("ftp://")) { uri = ftpAddress; } else { uri = "ftp://" + ftpAddress; } if (!string.IsNullOrEmpty(folderName)) { uri = uri.TrimEnd('/') + "/" + folderName; } if (!string.IsNullOrEmpty(fileName)) { uri = uri.TrimEnd('/') + "/" + fileName; } FtpWebRequest request = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri)); request.Credentials = new NetworkCredential(sftpUsername, sftpPassword); request.KeepAlive = false; request.Method = WebRequestMethods.Ftp.UploadFile; request.UseBinary = true; request.ContentLength = fileStream.Length; byte[] buffer = fileStream.GetBuffer(); Stream stream = request.GetRequestStream(); stream.Write(buffer, 0, buffer.Length); stream.Close(); }
9): 这里提供了另外一些比较常用的方法,可以根据自己的需要进行对应的调整~~
/// <summary> /// upload the file to ftp server. /// </summary> public void UploadByFtp(string ftpAddress, string filePath, string name) { FileStream fs = null; Stream stream = null; string uri = string.Empty; FileInfo fi = new FileInfo(filePath); if (ftpAddress.Contains("ftp://")) uri = ftpAddress + name; else uri = "ftp://" + ftpAddress + name; try { FtpWebRequest request = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri)); request.Credentials = new NetworkCredential(_username, _password); request.KeepAlive = false; request.Method = WebRequestMethods.Ftp.UploadFile; request.UseBinary = true; request.ContentLength = fi.Length; byte[] buffer = new byte[2048]; fs = fi.OpenRead(); stream = request.GetRequestStream(); int len = fs.Read(buffer, 0, buffer.Length); while (len != 0) { stream.Write(buffer, 0, len); len = fs.Read(buffer, 0, buffer.Length); } } catch (Exception e) { throw e; } finally { if (stream != null) stream.Close(); if (fs != null) fs.Close(); } } /// <summary> /// upload the file to ftp server. only for cover image process. /// </summary> public void UploadByFtp(string ftpAddress, MemoryStream fileStream, string fileName) { string uri = string.Empty; if (ftpAddress.Contains("ftp://")) uri = ftpAddress; else uri = "ftp://" + ftpAddress; FtpWebRequest request = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri + fileName)); request.Credentials = new NetworkCredential(_username, _password); request.KeepAlive = false; request.Method = WebRequestMethods.Ftp.UploadFile; request.UseBinary = true; request.ContentLength = fileStream.Length; byte[] buffer = fileStream.GetBuffer(); Stream stream = request.GetRequestStream(); stream.Write(buffer, 0, buffer.Length); stream.Close(); } /// <summary> /// delete the file from ftp server by ftp protocol. /// </summary> public void DeleteByFtp(string ftpAddress, string fileName) { string uri = string.Empty; if (ftpAddress.Contains("ftp://")) uri = ftpAddress + fileName; else uri = "ftp://" + ftpAddress + fileName; FtpWebRequest request = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri)); request.Credentials = new NetworkCredential(_username, _password); request.KeepAlive = false; request.Method = WebRequestMethods.Ftp.DeleteFile; request.GetResponse().Close(); } public void DownloadByFtp(string uri, MemoryStream stream, bool isInternalAuth) { if (!uri.Contains("ftp://")) uri = "ftp://" + uri; FtpWebRequest request = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri)); if (!isInternalAuth) request.Credentials = new NetworkCredential(_username, _password); request.KeepAlive = false; request.Method = WebRequestMethods.Ftp.DownloadFile; request.UseBinary = true; FtpWebResponse response = (FtpWebResponse)request.GetResponse(); Stream responseStream = response.GetResponseStream(); int len = 0; do { byte[] buffer = new byte[2048]; len = responseStream.Read(buffer, 0, buffer.Length); stream.Write(buffer, 0, len); } while (len > 0); responseStream.Close(); response.Close(); stream.Position = 0; } /// <summary> /// create the directory on ftp server. /// </summary> public void CreateDirectory(string ftpAddress, string directory) { string uri = string.Empty; if (ftpAddress.Contains("ftp://")) uri = ftpAddress; else uri = "ftp://" + ftpAddress; FtpWebRequest request = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri + directory)); request.Credentials = new NetworkCredential(_username, _password); request.KeepAlive = false; request.Method = WebRequestMethods.Ftp.MakeDirectory; request.GetResponse().Close(); } /// <returns>0: successful; 1: can not delete(e.g. have sub-dirs or sub-files); -1: failure</returns> public int RemoveDirectory(string ftpAddress, string directory) { int result; string uri = string.Empty; if (ftpAddress.Contains("ftp://")) uri = ftpAddress; else uri = "ftp://" + ftpAddress; FtpWebRequest request = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri + directory)); request.Credentials = new NetworkCredential(_username, _password); request.KeepAlive = false; request.Method = WebRequestMethods.Ftp.RemoveDirectory; try { request.GetResponse().Close(); result = 0; } catch (WebException we) { if (((FtpWebResponse)we.Response).StatusCode == FtpStatusCode.ActionNotTakenFileUnavailable) { result = -1; } else { result = 1; throw we; } } catch (Exception e) { result = 1; throw e; } return result; } public string[] GetFileList(string ftpAddress, string directory, bool isInternalAuth) { string uri = string.Empty; StringBuilder result = new StringBuilder(); if (ftpAddress.Contains("ftp://")) uri = ftpAddress; else uri = "ftp://" + ftpAddress; FtpWebRequest request = null; if (!string.IsNullOrEmpty(directory)) request = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri + directory)); else request = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri)); if (!isInternalAuth) request.Credentials = new NetworkCredential(_username, _password); request.KeepAlive = false; request.Method = WebRequestMethods.Ftp.ListDirectory; WebResponse response = request.GetResponse(); StreamReader reader = new StreamReader(response.GetResponseStream()); string line = reader.ReadLine(); while (line != null) { result.Append(line); result.Append("/"); line = reader.ReadLine(); } reader.Close(); response.Close(); if (result.Length > 0) return result.ToString().TrimEnd('/').Split('/'); else return null; } /// <returns>0: exist; -1: not exist; 1: unknown (other cause)</returns> public int IsExist(string ftpAddress, string directory) { string uri = string.Empty; int result; if (ftpAddress.Contains("ftp://")) uri = ftpAddress; else uri = "ftp://" + ftpAddress; FtpWebRequest request = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri + directory)); request.Credentials = new NetworkCredential(_username, _password); request.KeepAlive = false; request.Method = WebRequestMethods.Ftp.ListDirectory; try { request.GetResponse().Close(); result = 0; } catch (WebException we) { if (((FtpWebResponse)we.Response).StatusCode == FtpStatusCode.ActionNotTakenFileUnavailable) { result = -1; } else { result = 1; throw we; } } catch (Exception e) { result = 1; throw e; } return result; }