using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.IO;
using System.Text.RegularExpressions;
namespace FtpDemo
{
class FtpUpDown
{
#region 属性列表 Properties
/// <summary>
/// 服务器地址,可以是IP,也可以是FTP网址
/// </summary>
private string FtpServerAddress;
/// <summary>
/// 用户名
/// </summary>
private string FtpUserName;
/// <summary>
/// 用户密码
/// </summary>
private string FtpPassword;
/// <summary>
/// FTP请求
/// </summary>
private FtpWebRequest ftpRequest;
#endregion
#region 构造函数 Structure
public FtpUpDown(string ftpServer, string ftpUserName, string ftpPassword)
: this(ftpServer, ftpUserName, ftpPassword, 0)
{ }
/// <summary>
/// FTP上传下载
/// </summary>
/// <param name="ftpServer">服务器IP</param>
/// <param name="ftpUserName">用户名</param>
/// <param name="ftpPassword">密码</param>
/// <param name="ftpServerPort">服务器端口</param>
public FtpUpDown(string ftpServer, string ftpUserName, string ftpPassword, int ftpServerPort)
{
this.FtpServerAddress = ftpServer;
this.FtpUserName = ftpUserName;
this.FtpPassword = ftpPassword;
//如果端口号大于零,则代表已经指定了端口号,否则使用默认端口。
this.FtpServerAddress += (ftpServerPort > 0 ? string.Format(":{0}", ftpServerPort) : string.Empty);
}
#endregion
#region 私有方法 Private methods
/// <summary>
/// 连接服务器
/// </summary>
private void Connect()
{
Connect("ftp://" + FtpServerAddress + "/");
}
/// <summary>
/// 连接服务器
/// </summary>
/// <param name="path">FTP服务器要连接的路径</param>
private void Connect(String path)
{
// 根据FTP路径创建FtpWebRequest对象
ftpRequest = (FtpWebRequest)FtpWebRequest.Create(path);
// 指定数据传输类型
ftpRequest.UseBinary = true;
//是否使用被动模式,主动FTP模式与被动FTP模式,可以参考下面的网页
ftpRequest.UsePassive = false;
// ftp用户名和密码,创建与FTP进行连接的凭证。
ftpRequest.Credentials = new NetworkCredential(FtpUserName, FtpPassword);
}
/// <summary>
/// 获得指定目录中的文件列表
/// </summary>
/// <param name="path">指定目录</param>
/// <param name="WRMethods">发送到FTP服务器的命令【WebRequestMethods类中的值】</param>
/// <returns></returns>
private string[] GetFileList(string path, string WRMethods)
{
//最终要返回的文件(或目录)列表
List<string> fileList = new List<string>();
try
{
//连接指定目录
Connect(path);
//确定要执行的方法【读取目录?还是……?在此指定。】
ftpRequest.Method = WRMethods;
//接收服务器响应
WebResponse response = ftpRequest.GetResponse();
StreamReader reader = new StreamReader(response.GetResponseStream(), System.Text.Encoding.Default);//中文文件名
string line = reader.ReadLine();
while (line != null)
{
//循环读取并记录响应内容
fileList.Add(line);
line = reader.ReadLine();
}
reader.Close();
response.Close();
return fileList.ToArray();
}
catch (Exception ex)
{
//抛出错误,谁调用谁处理,偶就是不管。
throw ex;
}
}
#endregion
#region 公共方法 Public Methods
/// <summary>
/// 1、测试连接
/// </summary>
/// <param name="errorInfo">返回的错误信息</param>
/// <returns>是否测试成功</returns>
public bool TestConnection(out string errorInfo)
{
errorInfo = string.Empty;
try
{
//试图读取服务器端文件列表
this.GetFileList();
//读取成功,则代码连接无误
return true;
}
catch (Exception ex)
{
//出错,则连接不对。
errorInfo = "【连接错误】详细信息是:" + ex.Message;
return false;
}
}
/// <summary>
/// 2、从ftp服务器上获得根目录文件列表
/// </summary>
/// <returns></returns>
public string[] GetFileList()
{
return GetFileList("ftp://" + FtpServerAddress + "/", WebRequestMethods.Ftp.ListDirectory);
}
/// <summary>
/// 从ftp服务器上获得指定文件列表
/// </summary>
/// <param name="path">请求的路径【相对路径】</param>
/// <returns></returns>
public string[] GetFileList(string path)
{
return GetFileList("ftp://" + FtpServerAddress + "/" + path, WebRequestMethods.Ftp.ListDirectory);
}
/// <summary>
/// 3、向服务器上传文件
/// </summary>
/// <param name="filename">本地文件路径</param>
/// <param name="serverPath">服务器端的相对路径【例: uploads/myfiles 】两端不要加斜杠</param>
public void Upload(string filename, string serverPath)
{
Upload(filename, serverPath, null);
}
/// <summary>
/// 向服务器上传文件
/// </summary>
/// <param name="filename">本地文件路径</param>
/// <param name="serverPath">服务器端的相对路径【例: uploads/myfiles 】两端不要加斜杠</param>
/// <param name="transProcess">传输进度</param>
public void Upload(string filename, string serverPath, TransmissionProcess transProcess)
{
//检查传输进度
if (transProcess == null)
{
transProcess = new TransmissionProcess();
}
FileInfo fileInf = new FileInfo(filename);
string uri = string.Format("ftp://{0}/{1}/{2}", FtpServerAddress, serverPath, fileInf.Name);
transProcess.FileName = uri;//文件名
transProcess.TotalBytes = fileInf.Length;//文件大小
Connect(uri);//连接
//默认为true,连接不会被关闭
//在一个命令之后被执行
ftpRequest.KeepAlive = false;
//指定执行什么命令
ftpRequest.Method = WebRequestMethods.Ftp.UploadFile;
//上传文件时通知服务器文件的大小
ftpRequest.ContentLength = fileInf.Length;
//缓冲大小设置为kb
int buffLength = 2048;
byte[] buff = new byte[buffLength];
//打开一个文件流(System.IO.FileStream) 去读上传的文件
FileStream fs = fileInf.OpenRead();
try
{
//把上传的文件写入流
Stream strm = ftpRequest.GetRequestStream();
//每次读文件流的byte数目
int contentLen = fs.Read(buff, 0, buffLength);
//流内容没有结束
while (contentLen != 0)
{
//改变传输状态
if (transProcess.TransStatus != TransferStatus.InTransit)
transProcess.TransStatus = TransferStatus.InTransit;
//把内容从file stream 写入upload stream
strm.Write(buff, 0, contentLen);
//通知追加进度
transProcess.AppendBytes(contentLen);
contentLen = fs.Read(buff, 0, buffLength);
}
//关闭两个流
strm.Close();
fs.Close();
//传输结束
transProcess.TransStatus = TransferStatus.TranFinished;
}
catch (Exception ex)
{
transProcess.TransStatus = TransferStatus.Failed;
throw new Exception(string.Format("向服务器上传文件时出错!/n/n{0}", ex.Message));
}
}
/// <summary>
/// 4、从ftp服务器下载文件
/// </summary>
/// <param name="filePath">要保存文件的本地目录</param>
/// <param name="fileName">远程文件的路径【示例:uploads/myfile.rar】</param>
/// <param name="overWriteLocalFile">是否覆盖本地文件</param>
/// <param name="errorinfo">下载失败时,输出的错误信息</param>
/// <returns>是否下载成功</returns>
public bool Download(string filePath, string fileName, bool overWriteLocalFile, out string errorinfo)
{
return Download(filePath, fileName, overWriteLocalFile, null, out errorinfo);
}
/// <summary>
/// 从ftp服务器下载文件
/// </summary>
/// <param name="filePath">要保存文件的本地目录</param>
/// <param name="fileName">远程文件的路径【示例:uploads/myfile.rar】</param>
/// <param name="overWriteLocalFile">是否覆盖本地文件</param>
/// <param name="transProcess">传输进度</param>
/// <param name="errorinfo">下载失败时,输出的错误信息</param>
/// <returns>是否下载成功</returns>
public bool Download(string filePath, string fileName, bool overWriteLocalFile, TransmissionProcess transProcess, out string errorinfo)
{
//检查传输进度
if (transProcess == null)
{
transProcess = new TransmissionProcess();
}
errorinfo = string.Empty;
try
{
String onlyFileName = Path.GetFileName(fileName);
string newFileName = filePath + "//" + onlyFileName;
if (File.Exists(newFileName) && overWriteLocalFile == false)
{
transProcess.TransStatus = TransferStatus.Failed;
errorinfo = string.Format("本地文件{0}已存在,无法下载", newFileName);
return false;
}
//检查本地文件是否被占用
if (File.Exists(newFileName))
{
try
{
File.Move(newFileName, newFileName);
}
catch
{
transProcess.TransStatus = TransferStatus.Failed;
errorinfo = "本地文件被占用!无法覆盖!";
return false;
}
}
string url = "ftp://" + FtpServerAddress + "/" + fileName;
Connect(url);//连接
ftpRequest.Credentials = new NetworkCredential(FtpUserName, FtpPassword);
FtpWebResponse response = (FtpWebResponse)ftpRequest.GetResponse();
Stream ftpStream = response.GetResponseStream();
long cl = response.ContentLength;
int bufferSize = 2048;
int readCount;
byte[] buffer = new byte[bufferSize];
transProcess.FileName = url;
transProcess.TotalBytes = cl;
//改变传输状态
if (transProcess.TransStatus != TransferStatus.InTransit)
transProcess.TransStatus = TransferStatus.InTransit;
readCount = ftpStream.Read(buffer, 0, bufferSize);
transProcess.AppendBytes(readCount);
FileStream outputStream = new FileStream(newFileName, FileMode.Create, FileAccess.Write);
while (readCount > 0)
{
outputStream.Write(buffer, 0, readCount);
readCount = ftpStream.Read(buffer, 0, bufferSize);
transProcess.AppendBytes(readCount);
}
ftpStream.Close();
outputStream.Close();
response.Close();
//完成传输
transProcess.FinishBytes();
//下载成功
return true;
}
catch (Exception ex)
{
transProcess.TransStatus = TransferStatus.Failed;
errorinfo = string.Format("因{0},无法下载", ex.Message);
return false;
}
}
/// <summary>
/// 5、删除指定文件
/// </summary>
/// <param name="fileName">远程文件的路径【示例:uploads/myfile.rar】</param>
public void DeleteFileName(string fileName)
{
string uri = "ftp://" + FtpServerAddress + "/" + fileName;
try
{
Connect(uri);//连接
// 默认为true,连接不会被关闭
// 在一个命令之后被执行
ftpRequest.KeepAlive = false;
// 指定执行什么命令
ftpRequest.Method = WebRequestMethods.Ftp.DeleteFile;
FtpWebResponse response = (FtpWebResponse)ftpRequest.GetResponse();
response.Close();
}
catch (Exception ex)
{
throw new Exception(string.Format("删除文件“{0}”时出错!/n/n{1}", uri, ex.Message));
}
}
/// <summary>
/// 6、创建远程目录
/// </summary>
/// <param name="dirPath">远程文件夹路径</param>
/// <returns></returns>
public bool CreateDirectory(string dirPath)
{
try
{
string dirUri = "ftp://" + FtpServerAddress + "/" + dirPath;
this.Connect(dirUri);
ftpRequest.KeepAlive = false;
ftpRequest.Method = WebRequestMethods.Ftp.MakeDirectory;
ftpRequest.Proxy = null;
FtpWebResponse uploadResponse = (FtpWebResponse)ftpRequest.GetResponse();
uploadResponse.Close();
return true;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
return false;
}
}
/// <summary>
/// 7、删除目录
/// </summary>
/// <param name="dirPath">远程文件夹名【例如: uploads/oldDir】</param>
/// <returns></returns>
public bool DeleteDirectory(string dirPath)
{
try
{
string uri = "ftp://" + FtpServerAddress + "/" + dirPath;
Connect(uri);//连接
ftpRequest.Method = WebRequestMethods.Ftp.RemoveDirectory;
FtpWebResponse response = (FtpWebResponse)ftpRequest.GetResponse();
response.Close();
return true;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
return false;
}
}
/// <summary>
/// 8、获得文件大小
/// </summary>
/// <param name="filename">远程文件的路径【示例:uploads/myfile.rar】</param>
/// <returns></returns>
public long GetFileSize(string filename)
{
long fileSize = 0;
string uri = "ftp://" + FtpServerAddress + "/" + filename;
try
{
Connect(uri);//连接
ftpRequest.Method = WebRequestMethods.Ftp.GetFileSize;
FtpWebResponse response = (FtpWebResponse)ftpRequest.GetResponse();
fileSize = response.ContentLength;
response.Close();
}
catch (Exception ex)
{
throw new Exception(string.Format("获得文件“{0}”大小时出错!/n/n{1}", uri, ex.Message));
}
//成功返回大小
return fileSize;
}
/// <summary>
/// 9、重命名文件
/// </summary>
/// <param name="currentFilename">远程文件的路径【示例:uploads/myfile.rar】</param>
/// <param name="newFilename">新名【不需要路径,但要包含后缀】</param>
public void Rename(string currentFilename, string newFilename)
{
string uri = "ftp://" + FtpServerAddress + "/" + currentFilename;
try
{
Connect(uri);//连接
ftpRequest.Method = WebRequestMethods.Ftp.Rename;
ftpRequest.RenameTo = newFilename;
FtpWebResponse response = (FtpWebResponse)ftpRequest.GetResponse();
response.Close();
}
catch (Exception ex)
{
throw new Exception(string.Format("重命名文件“{0}”大小时出错!/n/n{1}", uri, ex.Message));
}
}
/// <summary>
/// 10、获得根目录文件明晰
/// </summary>
/// <returns></returns>
public string[] GetFilesDetailList()
{
return GetFilesDetailList(string.Empty);
}
/// <summary>
/// 获得指定目录中的文件明晰
/// </summary>
/// <param name="path">指定目录【示例: upload/yan】</param>
/// <returns></returns>
public string[] GetFilesDetailList(string path)
{
return GetFileList("ftp://" + FtpServerAddress + "/" + path, WebRequestMethods.Ftp.ListDirectoryDetails);
}
/// <summary>
/// 获取根目录下所有的文件夹列表(仅文件夹)
/// </summary>
/// <returns></returns>
public string[] GetDirectoryList()
{
string[] drectory = GetFilesDetailList();
string m = string.Empty;
foreach (string str in drectory)
{
if (str.Trim().Substring(25, 1).ToUpper() == "D")
{
m += str.Trim() + "/n";
}
}
char[] n = new char[] { '/n' };
return m.Split(n);
}
/// <summary>
/// 获取指定目录下所有的文件夹列表(仅文件夹)
/// </summary>
/// <returns></returns>
public string[] GetDirectoryList(string path)
{
//最终要返回的文件列表
StringBuilder result = new StringBuilder();
try
{
Connect("ftp://" + FtpServerAddress + "/");//连接
ftpRequest.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
WebResponse response = ftpRequest.GetResponse();
StreamReader reader = new StreamReader(response.GetResponseStream(), System.Text.Encoding.Default);
string line = reader.ReadLine();
while (line != null)
{
if (line.IndexOf("<DIR>") != -1)
{
result.Append(line);
result.Append("/n");
}
line = reader.ReadLine();
}
result.Remove(result.ToString().LastIndexOf('/n'), 1);
reader.Close();
response.Close();
}
catch (Exception ex)
{
throw (ex);
}
return result.ToString().Split('/n');
}
/// <summary>
/// 获取根目录下文件列表(仅文件)
/// </summary>
/// <returns></returns>
public string[] GetFileNameList()
{
//最终要返回的文件列表
StringBuilder result = new StringBuilder();
try
{
Connect("ftp://" + FtpServerAddress + "/");//连接
ftpRequest.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
WebResponse response = ftpRequest.GetResponse();
StreamReader reader = new StreamReader(response.GetResponseStream(), System.Text.Encoding.Default);
string line = reader.ReadLine();
while (line != null)
{
if (line.IndexOf("<DIR>")==-1)
{
result.Append(Regex.Match(line, @"[/S]+ [/S]+", RegexOptions.IgnoreCase).Value.Split(' ')[1]);
result.Append("/n");
}
line = reader.ReadLine();
}
result.Remove(result.ToString().LastIndexOf('/n'), 1);
reader.Close();
response.Close();
}
catch (Exception ex)
{
throw (ex);
}
return result.ToString().Split('/n');
}
#endregion
}
}