最近做的项目需要用到FTP传输文件,所以写这么一个帮助类,功能比较简单,可以实现基本的上传和下载,包括递归下载文件夹,代码如下:
public class FtpAccess : IDisposable
{
#region 私有变量
/// <summary>
/// Ftp请求对象
/// </summary>
private FtpWebRequest _request = null;
/// <summary>
/// Ftp响应对象
/// </summary>
private FtpWebResponse _response = null;
/// <summary>
/// 是否需要删除临时文件
/// </summary>
private bool _isDeleteTempFile = false;
/// <summary>
/// 异步上传时临时生成的文件
/// </summary>
private string _uploadTempFile = "";
#endregion
#region 公共属性
///<summary>
/// Ftp服务器地址:wifi.ttoocc.com/
/// </summary>
public string ServerUri { get; set; }
/// <summary>
/// Ftp服务器登录用户
/// </summary>
public string UserName { get; set; }
/// <summary>
/// Ftp服务器登录密码
/// </summary>
public string Password { get; set; }
#endregion
#region 构造函数
public FtpAccess() { }
/// <summary>
/// 实例化FTP帮助类
/// </summary>
/// <param name="serverUri">FTP服务器地址(IP或域名)</param>
/// <param name="userName">FTP用户名</param>
/// <param name="password">FTP密码</param>
public FtpAccess(string serverUri, string userName, string password)
{
ServerUri = serverUri;
UserName = userName;
Password = password;
}
#endregion
#region 实现接口
public void Dispose()
{
if (_request != null)
{
_request.Abort();
_request = null;
}
if (_response != null)
{
_response.Close();
_response = null;
}
}
#endregion
#region 事件
/// <summary>
/// 上传文件
/// </summary>
/// <param name="fileLocalPath">需要上传的文件</param>
/// <param name="remoteDir">目标路径</param>
/// <param name="newFileName">新的文件名</param>
public bool UploadFile(string fileLocalPath, string remoteDir, string newFileName)
{
FileInfo file = new FileInfo(fileLocalPath);
if (remoteDir.Trim() == "")
{
return false;
}
string URI = "FTP://" + ServerUri + "/" + remoteDir + "/" + newFileName;
_request = null;
if (!FtpIsExistsDir(remoteDir))
{
CreateDir(remoteDir);
}
if (FtpIsExistsFile(remoteDir + "/" + newFileName))
{
_request = GetRequest(URI);
_request.KeepAlive = false;
_request.Method = System.Net.WebRequestMethods.Ftp.DeleteFile; //删除
_request.GetResponse();
}
//URI = "FTP://" + hostname + "/" + targetDir + "/" + newFileName;
_request = null;
_request = GetRequest(URI);
_request.UseBinary = true;
_request.UsePassive = true;
_request.KeepAlive = false;
_request.Method = System.Net.WebRequestMethods.Ftp.UploadFile;
//指定文件传输的数据类型
//告诉ftp文件大小
_request.ContentLength = file.Length;
//缓冲大小设置为2KB
int BufferSize = 2048, lastBufferSize, count;
//计算包个数
count = (int)file.Length / BufferSize + 1;
//计算最后一个包大小
lastBufferSize = (int)file.Length % BufferSize;
byte[] content = new byte[BufferSize];
int dataRead;
//打开一个文件流 (System.IO.FileStream) 去读上传的文件
using (FileStream fs = file.OpenRead())
{
try
{
//把上传的文件写入流
using (Stream rs = _request.GetRequestStream())
{
while (count > 1)
{
dataRead = fs.Read(content, 0, BufferSize);
rs.Write(content, 0, BufferSize);
count--;
}
content = new byte[lastBufferSize];
dataRead = fs.Read(content, 0, lastBufferSize);
rs.Write(content, 0, lastBufferSize);
rs.Close();
rs.Dispose();
fs.Close();
fs.Dispose();
return true;
}
}
catch (Exception)
{
return false;
}
finally
{
fs.Close();
fs.Dispose();
}
}
}
/// <summary>
/// 下载文件
/// </summary>
/// <param name="localDir">下载至本地路径</param>
/// <param name="ftpDir">ftp目标文件路径</param>
/// <param name="ftpFile">从ftp要下载的文件名</param>
public void DownloadFile(string localDir, string ftpDir, string ftpFile)
{
string URI = "FTP://" + ServerUri + "/" + ftpDir + "/" + ftpFile;
string tmpname = Guid.NewGuid().ToString();
string localfile = localDir + @"\" + tmpname;
if (!Directory.Exists(localDir))
Directory.CreateDirectory(localDir);
_request = GetRequest(URI);
_request.Method = System.Net.WebRequestMethods.Ftp.DownloadFile;
_request.UseBinary = true;
_request.UsePassive = false;
using (FtpWebResponse response = (FtpWebResponse)_request.GetResponse())
{
using (Stream responseStream = response.GetResponseStream())
{
using (FileStream fs = new FileStream(localfile, FileMode.CreateNew))
{
try
{
byte[] buffer = new byte[2048];
int read = 0;
do
{
read = responseStream.Read(buffer, 0, buffer.Length);
fs.Write(buffer, 0, read);
} while (read != 0);
responseStream.Close();
fs.Flush();
fs.Close();
}
catch (Exception)
{
fs.Close();
File.Delete(localfile);
throw;
}
}
responseStream.Close();
}
response.Close();
}
try
{
File.Delete(localDir + @"\" + ftpFile);
File.Move(localfile, localDir + @"\" + ftpFile);
}
catch (Exception ex)
{
File.Delete(localfile);
throw ex;
}
_request = null;
}
/// <summary>
/// 从FTP上下载文件夹及其内容(递归)
/// </summary>
/// <param name="localDir"></param>
/// <param name="ftpDir"></param>
/// <returns></returns>
public bool DownloadDirectory(string localDir, string ftpDir)
{
var list = GetDirectoriesListInfo(ftpDir);
foreach (var item in list)
{
if (item.Groups[1].Value == "d")
{
DownloadDirectory(localDir + @"\" + item.Groups[6].Value, ftpDir + "/" + item.Groups[6].Value);
}
else
{
var file = new FileInfo(localDir + @"\" + item.Groups[6].Value);
if (file.Exists)
{
var ftpDateTime = GetLastModified(ftpDir + @"\" + item.Groups[6].Value);
var localDataTime = file.LastWriteTime;
if (ftpDateTime <= localDataTime)//若本地文件比FTP文件新,则不用下载该文件
continue;
}
DownloadFile(localDir, ftpDir, item.Groups[6].Value);
}
}
return true;
}
/// <summary>
/// 搜索远程文件
/// </summary>
/// <param name="targetDir">远程文件夹(不能以"/"结尾) e.q. "aaa/bbb/ccc"</param>
/// <returns></returns>
public List<string> GetDirectoriesList(string targetDir)
{
var lastDirName = targetDir.Substring(targetDir.LastIndexOf('/') + 1);
List<string> result = new List<string>();
try
{
string URI = "FTP://" + ServerUri + "/" + targetDir;
_request = GetRequest(URI);
_request.Method = System.Net.WebRequestMethods.Ftp.ListDirectory;
_request.UsePassive = true;
_request.UseBinary = true;
string str = GetStringResponse(_request);
str = str.Replace(lastDirName + "/", null);
if (str != string.Empty)
result.AddRange(str.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries));
return result;
}
catch { return null; }
}
public List<string> GetDirectoriesList(string targetDir, string searchKey)
{
var lastDirName = targetDir.Substring(targetDir.LastIndexOf('/') + 1);
List<string> result = new List<string>();
try
{
string URI = "FTP://" + ServerUri + "/" + targetDir;
_request = GetRequest(URI);
_request.Method = System.Net.WebRequestMethods.Ftp.ListDirectory;
_request.UsePassive = true;
_request.UseBinary = true;
string str = GetStringResponse(_request);
str = str.Replace(lastDirName + "/", null);
if (str != string.Empty)
result.AddRange(str.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries));
return result.Where(m => m.Contains(searchKey)).ToList();
}
catch { return null; }
}
/// <summary>
/// 获取FTP指定目录下文件及文件夹列表
/// </summary>
/// <param name="targetDir"></param>
/// <returns></returns>
public List<Match> GetDirectoriesListInfo(string targetDir)
{
var lastDirName = targetDir.Substring(targetDir.LastIndexOf('/') + 1);
List<Match> result = new List<Match>();
try
{
string URI = "FTP://" + ServerUri + "/" + targetDir;
_request = GetRequest(URI);
_request.Method = System.Net.WebRequestMethods.Ftp.ListDirectoryDetails;
_request.UsePassive = true;
_request.UseBinary = true;
string str = GetStringResponse(_request);
List<string> strs = new List<string>();
if (str != string.Empty)
strs.AddRange(str.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries));
Regex regex = new Regex(@"^([d-])([rwxt-]{3}){3}\s+\d{1,}\s+.*?(\d{1,})\s+(\w+\s+\d{1,2}\s+(?:\d{4})?)(\d{1,2}:\d{2})?\s+(.+?)\s?$", RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);
foreach (var item in strs)
{
Match match = regex.Match(item);
result.Add(match);
}
return result;
}
catch { return null; }
}
/// <summary>
/// 获取文件或文件夹的最后修改时间
/// </summary>
/// <param name="path">路径</param>
/// <returns></returns>
private DateTime GetLastModified(string path)
{
try
{
string uri = "ftp://" + ServerUri + "/" + path;
_request = GetRequest(uri);
_request.Method = WebRequestMethods.Ftp.GetDateTimestamp;
_response = (FtpWebResponse)_request.GetResponse();
return _response.LastModified;
}
catch (Exception)
{
return DateTime.MinValue;
}
}
/// <summary>
/// 在ftp服务器上创建目录
/// </summary>
/// <param name="dirName">目录名称</param>
/// <returns></returns>
public bool CreateDir(string dirName)
{
try
{
string uri = "ftp://" + ServerUri + "/" + dirName;
_request = GetRequest(uri);
_request.Method = WebRequestMethods.Ftp.MakeDirectory;
_response = (FtpWebResponse)_request.GetResponse();
_response.Close();
return true;
}
catch (Exception)
{
return false;
}
}
/// <summary>
/// 删除目录
/// </summary>
/// <param name="dirName">删除的目录名称</param>
public bool DelDir(string dirName)
{
try
{
string uri = "ftp://" + ServerUri + "/" + dirName;
_request = GetRequest(uri);
_request.Method = WebRequestMethods.Ftp.RemoveDirectory;
_response = (FtpWebResponse)_request.GetResponse();
_response.Close();
return true;
}
catch (Exception)
{
return false;
}
}
/// <summary>
/// 文件重命名
/// </summary>
/// <param name="currentFilename">当前目录名称</param>
/// <param name="newFilename">重命名目录名称</param>
public bool Rename(string currentFilename, string newFilename)
{
try
{
FileInfo fileInf = new FileInfo(currentFilename);
string uri = "ftp://" + ServerUri + "/" + fileInf.Name;
_request = GetRequest(uri);
_request.Method = WebRequestMethods.Ftp.Rename;
_request.RenameTo = newFilename;
_response = (FtpWebResponse)_request.GetResponse();
_response.Close();
return true;
}
catch (Exception)
{
return false;
}
}
/// <summary>
/// 判断ftp服务器上该目录是否存在
/// </summary>
/// <param name="dirName"></param>
/// <param name="ftpHostIP"></param>
/// <param name="username"></param>
/// <param name="password"></param>
/// <returns></returns>
public bool FtpIsExistsDir(string dirName)
{
bool flag = true;
try
{
string uri = "ftp://" + ServerUri + "/" + dirName;
_request = GetRequest(uri);
_request.Method = WebRequestMethods.Ftp.ListDirectory;
_response = (FtpWebResponse)_request.GetResponse();
_response.Close();
}
catch (Exception)
{
flag = false;
}
return flag;
}
/// <summary>
/// 检测文件是否存在
/// </summary>
/// <param name="fileFullName"></param>
/// <param name="ftpHostIP"></param>
/// <param name="username"></param>
/// <param name="password"></param>
/// <returns></returns>
public bool FtpIsExistsFile(string fileFullName)
{
bool flag = true;
try
{
string uri = "ftp://" + ServerUri + "/" + fileFullName;
_request = GetRequest(uri);
_request.Method = WebRequestMethods.Ftp.GetFileSize;
_response = (FtpWebResponse)_request.GetResponse();
_response.Close();
}
catch (Exception)
{
flag = false;
}
return flag;
}
private FtpWebRequest GetRequest(string URI)
{
//根据服务器信息FtpWebRequest创建类的对象
FtpWebRequest result = (FtpWebRequest)FtpWebRequest.Create(URI);
//提供身份验证信息
result.Credentials = new System.Net.NetworkCredential(UserName, Password);
//设置请求完成之后是否保持到FTP服务器的控制连接,默认值为true
result.KeepAlive = false;
return result;
}
private string GetStringResponse(FtpWebRequest ftp)
{
//Get the result, streaming to a string
string result = "";
using (FtpWebResponse response = (FtpWebResponse)ftp.GetResponse())
{
long size = response.ContentLength;
using (Stream datastream = response.GetResponseStream())
{
using (StreamReader sr = new StreamReader(datastream, System.Text.Encoding.UTF8))
{
result = sr.ReadToEnd();
sr.Close();
}
datastream.Close();
}
response.Close();
}
return result;
}
#endregion
}