最近做的項目需要用到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
}