ftp 操作,支持断点续传或者继续下载。
1、ftpclient 类
public class FTPClient:IDisposable
{
public static object _obj = new object(); #region 构造函数
/// <summary>
/// 缺省构造函数
/// </summary>
public FTPClient()
{
_strRemoteHost = "";
_strRemotePath = "";
_strRemoteUser = "";
_strRemotePass = "";
_strRemotePort = 21;
_bConnected = false;
} /// <summary>
/// 构造函数
/// </summary>
public FTPClient(string remoteHost, string remotePath, string remoteUser, string remotePass, int remotePort)
{
_strRemoteHost = remoteHost;
_strRemotePath = remotePath;
_strRemoteUser = remoteUser;
_strRemotePass = remotePass;
_strRemotePort = remotePort;
Connect();
}
#endregion #region 字段
private int _strRemotePort;
private Boolean _bConnected;
private string _strRemoteHost;
private string _strRemotePass;
private string _strRemoteUser;
private string _strRemotePath; /// <summary>
/// 服务器返回的应答信息(包含应答码)
/// </summary>
private string _strMsg;
/// <summary>
/// 服务器返回的应答信息(包含应答码)
/// </summary>
private string _strReply;
/// <summary>
/// 服务器返回的应答码
/// </summary>
private int _iReplyCode;
/// <summary>
/// 进行控制连接的socket
/// </summary>
private Socket _socketControl;
/// <summary>
/// 传输模式
/// </summary>
private TransferType _trType;
/// <summary>
/// 接收和发送数据的缓冲区
/// </summary>
private static int _BLOCK_SIZE = 512;
/// <summary>
/// 编码方式
/// </summary>
Encoding _ASCII = Encoding.UTF8;
/// <summary>
/// 字节数组
/// </summary>
Byte[] _buffer = new Byte[_BLOCK_SIZE];
#endregion #region 属性
/// <summary>
/// FTP服务器IP地址
/// </summary>
public string RemoteHost
{
get
{
return _strRemoteHost;
}
set
{
_strRemoteHost = value;
}
} /// <summary>
/// FTP服务器端口
/// </summary>
public int RemotePort
{
get
{
return _strRemotePort;
}
set
{
_strRemotePort = value;
}
} /// <summary>
/// 当前服务器目录
/// </summary>
public string RemotePath
{
get
{
return _strRemotePath;
}
set
{
_strRemotePath = value;
}
} /// <summary>
/// 登录用户账号
/// </summary>
public string RemoteUser
{
set
{
_strRemoteUser = value;
}
} /// <summary>
/// 用户登录密码
/// </summary>
public string RemotePwd
{
set
{
_strRemotePass = value;
}
} /// <summary>
/// 是否登录
/// </summary>
public bool Connected
{
get
{
return _bConnected;
}
}
#endregion #region 链接
/// <summary>
/// 建立连接
/// </summary>
public void Connect()
{
lock (_obj)
{
_socketControl = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint ep = new IPEndPoint(IPAddress.Parse(RemoteHost), _strRemotePort);
try
{
_socketControl.Connect(ep);
}
catch (Exception)
{
throw new IOException("不能连接ftp服务器");
}
}
ReadReply();
if (_iReplyCode != 220)
{
DisConnect();
throw new IOException(_strReply.Substring(4));
}
SendCommand("USER " + _strRemoteUser);
if (!(_iReplyCode == 331 || _iReplyCode == 230))
{
CloseSocketConnect();
throw new IOException(_strReply.Substring(4));
}
if (_iReplyCode != 230)
{
SendCommand("PASS " + _strRemotePass);
if (!(_iReplyCode == 230 || _iReplyCode == 202))
{
CloseSocketConnect();
throw new IOException(_strReply.Substring(4));
}
}
_bConnected = true;
ChDir(_strRemotePath);
} /// <summary>
/// 关闭连接
/// </summary>
public void DisConnect()
{
if (_socketControl != null)
{
SendCommand("QUIT");
}
CloseSocketConnect();
}
#endregion #region 传输模式
/// <summary>
/// 传输模式:二进制类型、ASCII类型
/// </summary>
public enum TransferType { Binary, ASCII }; /// <summary>
/// 设置传输模式
/// </summary>
/// <param name="ttType">传输模式</param>
public void SetTransferType(TransferType ttType)
{
if (ttType == TransferType.Binary)
{
SendCommand("TYPE I");//binary类型传输
}
else
{
SendCommand("TYPE A");//ASCII类型传输
}
if (_iReplyCode != 200)
{
throw new IOException(_strReply.Substring(4));
}
else
{
_trType = ttType;
}
} /// <summary>
/// 获得传输模式
/// </summary>
/// <returns>传输模式</returns>
public TransferType GetTransferType()
{
return _trType;
}
#endregion #region 文件操作
/// <summary>
/// 获得文件列表
/// </summary>
/// <param name="strMask">文件名的匹配字符串</param>
public string[] Dir(string strMask)
{
if (!_bConnected)
{
Connect();
}
Socket socketData = CreateDataSocket();
SendCommand("NLST " + strMask);
if (!(_iReplyCode == 150 || _iReplyCode == 125 || _iReplyCode == 226))
{
throw new IOException(_strReply.Substring(4));
}
_strMsg = "";
Thread.Sleep(2000);
while (true)
{
int iBytes = socketData.Receive(_buffer, _buffer.Length, 0);
_strMsg += _ASCII.GetString(_buffer, 0, iBytes);
if (iBytes < _buffer.Length)
{
break;
}
}
char[] seperator = { '\n' };
string[] strsFileList = _strMsg.Split(seperator);
socketData.Close(); //数据socket关闭时也会有返回码
if (_iReplyCode != 226)
{
ReadReply();
if (_iReplyCode != 226)
{ throw new IOException(_strReply.Substring(4));
}
}
return strsFileList;
} public void newPutByGuid(string strFileName, string strGuid)
{
if (!_bConnected)
{
Connect();
}
string str = strFileName.Substring(0, strFileName.LastIndexOf("\\"));
string strTypeName = strFileName.Substring(strFileName.LastIndexOf("."));
strGuid = str + "\\" + strGuid;
Socket socketData = CreateDataSocket();
SendCommand("STOR " + Path.GetFileName(strGuid));
if (!(_iReplyCode == 125 || _iReplyCode == 150))
{
throw new IOException(_strReply.Substring(4));
}
FileStream input = new FileStream(strGuid, FileMode.Open);
input.Flush();
int iBytes = 0;
while ((iBytes = input.Read(_buffer, 0, _buffer.Length)) > 0)
{
socketData.Send(_buffer, iBytes, 0);
}
input.Close();
if (socketData.Connected)
{
socketData.Close();
}
if (!(_iReplyCode == 226 || _iReplyCode == 250))
{
ReadReply();
if (!(_iReplyCode == 226 || _iReplyCode == 250))
{
throw new IOException(_strReply.Substring(4));
}
}
} /// <summary>
/// 获取文件大小
/// 当文件在ftp服务器上不存在时,报异常
/// </summary>
/// <param name="strFileName">文件名</param>
/// <returns>文件大小</returns>
public long GetFileSize(string strFileName)
{
if (!_bConnected)
{
Connect();
}
SendCommand("SIZE " + Path.GetFileName(strFileName));
long lSize = 0;
if (_iReplyCode == 213)
{
lSize = Int64.Parse(_strReply.Substring(4));
}
else
{
throw new IOException(_strReply.Substring(4));
}
return lSize;
} /// <summary>
/// 获取文件信息
/// </summary>
/// <param name="strFileName">文件名</param>
/// <returns>文件大小</returns>
public string GetFileInfo(string strFileName)
{
if (!_bConnected)
{
Connect();
}
Socket socketData = CreateDataSocket();
SendCommand("LIST " + strFileName);
string strResult = "";
if (!(_iReplyCode == 150 || _iReplyCode == 125
|| _iReplyCode == 226 || _iReplyCode == 250))
{
throw new IOException(_strReply.Substring(4));
}
byte[] b = new byte[512];
MemoryStream ms = new MemoryStream(); while (true)
{
int iBytes = socketData.Receive(b, b.Length, 0);
ms.Write(b, 0, iBytes);
if (iBytes <= 0)
{ break;
}
}
byte[] bt = ms.GetBuffer();
strResult = System.Text.Encoding.ASCII.GetString(bt);
ms.Close();
return strResult;
} /// <summary>
/// 删除
/// </summary>
/// <param name="strFileName">待删除文件名</param>
public void Delete(string strFileName)
{
if (!_bConnected)
{
Connect();
}
SendCommand("DELE " + strFileName);
if (_iReplyCode != 250)
{
throw new IOException(_strReply.Substring(4));
}
} /// <summary>
/// 重命名(如果新文件名与已有文件重名,将覆盖已有文件)
/// </summary>
/// <param name="strOldFileName">旧文件名</param>
/// <param name="strNewFileName">新文件名</param>
public void Rename(string strOldFileName, string strNewFileName)
{
if (!_bConnected)
{
Connect();
}
SendCommand("RNFR " + strOldFileName);
if (_iReplyCode != 350)
{
throw new IOException(_strReply.Substring(4));
}
// 如果新文件名与原有文件重名,将覆盖原有文件
SendCommand("RNTO " + strNewFileName);
if (_iReplyCode != 250)
{
throw new IOException(_strReply.Substring(4));
}
}
#endregion #region 上传和下载
/// <summary>
/// 下载一批文件
/// </summary>
/// <param name="strFileNameMask">文件名的匹配字符串</param>
/// <param name="strFolder">本地目录(不得以\结束)</param>
public void Get(string strFileNameMask, string strFolder)
{
if (!_bConnected)
{
Connect();
}
string[] strFiles = Dir(strFileNameMask);
foreach (string strFile in strFiles)
{
if (!strFile.Equals(""))//一般来说strFiles的最后一个元素可能是空字符串
{
Get(strFile, strFolder, strFile);
}
}
} /// <summary>
/// 下载一个文件
/// </summary>
/// <param name="strRemoteFileName">要下载的文件名</param>
/// <param name="strFolder">本地目录(不得以\结束)</param>
/// <param name="strLocalFileName">保存在本地时的文件名</param>
public void Get(string strRemoteFileName, string strFolder, string strLocalFileName="")
{
Socket socketData = CreateDataSocket();
try
{
if (!_bConnected)
{
Connect();
}
SetTransferType(TransferType.Binary); strLocalFileName = RegetFileName(strRemoteFileName, strLocalFileName); SendCommand("RETR " + strRemoteFileName);
if (!(_iReplyCode == 150 || _iReplyCode == 125 || _iReplyCode == 226 || _iReplyCode == 250))
{
throw new IOException(_strReply.Substring(4));
}
FileStream output = new FileStream(strFolder + "\\" + strLocalFileName, FileMode.Create);
while (true)
{
int iBytes = socketData.Receive(_buffer, _buffer.Length, 0);
output.Write(_buffer, 0, iBytes);
if (iBytes <= 0)
{
break;
}
}
output.Close();
if (socketData.Connected)
{
socketData.Close();
}
if (!(_iReplyCode == 226 || _iReplyCode == 250))
{
ReadReply();
if (!(_iReplyCode == 226 || _iReplyCode == 250))
{
throw new IOException(_strReply.Substring(4));
}
}
}
catch
{
socketData.Close();
socketData = null;
_socketControl.Close();
_bConnected = false;
_socketControl = null;
}
} /// <summary>
/// 下载一个文件,支持断点下载
/// </summary>
/// <param name="strRemoteFileName"></param>
/// <param name="strFolder"></param>
/// <param name="strLocalFileName"></param>
/// <param name="size"></param>
public void GetBrokenFile(string strRemoteFileName, string strFolder, string strLocalFileName="")
{
if (!_bConnected)
{
Connect();
}
SetTransferType(TransferType.Binary); strLocalFileName = RegetFileName(strRemoteFileName, strLocalFileName); long localFileSize = 0;
var localfileWithFullname = strFolder + "//" + strLocalFileName;
if (File.Exists(localfileWithFullname))
{
FileInfo fInfo = new FileInfo(localfileWithFullname);
localFileSize = fInfo.Length;
}
else
{
throw new Exception("localfile not exists!");
} FileStream output = new
FileStream(strFolder + "//" + strLocalFileName, FileMode.Append);
Socket socketData = CreateDataSocket();
SendCommand("REST " + localFileSize.ToString());
SendCommand("RETR " + strRemoteFileName);
if (!(_iReplyCode == 150 || _iReplyCode == 125
|| _iReplyCode == 226 || _iReplyCode == 250))
{
throw new IOException(_strReply.Substring(4));
} while (true)
{
int iBytes = socketData.Receive(_buffer, _buffer.Length, 0);
output.Write(_buffer, 0, iBytes);
if (iBytes <= 0)
{
break;
}
}
output.Close();
if (socketData.Connected)
{
socketData.Close();
}
if (!(_iReplyCode == 226 || _iReplyCode == 250))
{
ReadReply();
if (!(_iReplyCode == 226 || _iReplyCode == 250))
{
throw new IOException(_strReply.Substring(4));
}
}
} /// <summary>
/// 下载一个文件 ,智能判断是重新下载或者断点继续下载
/// 1、当本地文件不存在,或者大小等于0, 重新下载
/// 2、当本地文件存在, size>0 and size<totalsize, 断点下载
/// </summary>
/// <param name="strRemoteFileName"></param>
/// <param name="strFolder"></param>
/// <param name="strLocalFileName"></param>
public void GetFileByRestartOrBroken(string strRemoteFileName, string strFolder, string strLocalFileName = "")
{
strLocalFileName = RegetFileName(strRemoteFileName, strLocalFileName);
long remoteFileSize = 0;
long localFileSize = 0;
try
{
remoteFileSize = this.GetFileSize(strRemoteFileName);
}
catch (Exception ex)
{
throw new IOException(string.Format("由于 {0} 导致 GetFileByRestartOrBroken 出现异常", ex.Message));
} var localfileWithFullname = strFolder + "//" + strLocalFileName;
if (File.Exists(localfileWithFullname))
{
FileInfo fInfo = new FileInfo(localfileWithFullname);
localFileSize = fInfo.Length;
}
else
{
localFileSize = 0;
} if (localFileSize==0)
{
this.Get(strRemoteFileName, strFolder, strLocalFileName);
}
else
{
this.GetBrokenFile(strRemoteFileName, strFolder,strLocalFileName);
}
} /// <summary>
/// 下载一个文件
/// </summary>
/// <param name="strRemoteFileName">要下载的文件名</param>
/// <param name="strFolder">本地目录(不得以\结束)</param>
/// <param name="strLocalFileName">保存在本地时的文件名</param>
public void GetNoBinary(string strRemoteFileName, string strFolder, string strLocalFileName="")
{
if (!_bConnected)
{
Connect();
} strLocalFileName = RegetFileName(strRemoteFileName, strLocalFileName); Socket socketData = CreateDataSocket();
SendCommand("RETR " + strRemoteFileName);
if (!(_iReplyCode == 150 || _iReplyCode == 125 || _iReplyCode == 226 || _iReplyCode == 250))
{
throw new IOException(_strReply.Substring(4));
}
FileStream output = new FileStream(strFolder + "\\" + strLocalFileName, FileMode.Create);
while (true)
{
int iBytes = socketData.Receive(_buffer, _buffer.Length, 0);
output.Write(_buffer, 0, iBytes);
if (iBytes <= 0)
{
break;
}
}
output.Close();
if (socketData.Connected)
{
socketData.Close();
}
if (!(_iReplyCode == 226 || _iReplyCode == 250))
{
ReadReply();
if (!(_iReplyCode == 226 || _iReplyCode == 250))
{
throw new IOException(_strReply.Substring(4));
}
}
} /// <summary>
/// 上传一批文件
/// </summary>
/// <param name="strFolder">本地目录(不得以\结束)</param>
/// <param name="strFileNameMask">文件名匹配字符(可以包含*和?)</param>
public void Put(string strFolder, string strFileNameMask)
{
string[] strFiles = Directory.GetFiles(strFolder, strFileNameMask);
foreach (string strFile in strFiles)
{
Put(strFile);
}
} /// <summary>
/// 上传一个文件
/// </summary>
/// <param name="strFileName">本地文件名 fullName</param>
public void Put(string strFileName)
{
if (!_bConnected)
{
Connect();
}
Socket socketData = CreateDataSocket();
if (Path.GetExtension(strFileName) == "")
SendCommand("STOR " + Path.GetFileNameWithoutExtension(strFileName));
else
SendCommand("STOR " + Path.GetFileName(strFileName)); if (!(_iReplyCode == 125 || _iReplyCode == 150))
{
throw new IOException(_strReply.Substring(4));
} FileStream input = new FileStream(strFileName, FileMode.Open);
int iBytes = 0;
while ((iBytes = input.Read(_buffer, 0, _buffer.Length)) > 0)
{
socketData.Send(_buffer, iBytes, 0);
}
input.Close();
if (socketData.Connected)
{
socketData.Close();
}
if (!(_iReplyCode == 226 || _iReplyCode == 250))
{
ReadReply();
if (!(_iReplyCode == 226 || _iReplyCode == 250))
{
throw new IOException(_strReply.Substring(4));
}
}
} /// <summary>
/// 上传一个文件,支持断点上传
/// </summary>
/// <param name="strFileName">localfile with fullName</param>
/// <param name="remoteFileName">remoteFilename</param>
public void PutBrokenFile(string strFileName,string remoteFileName="")
{
if (!_bConnected)
{
Connect();
}
remoteFileName = RegetFileName(strFileName, remoteFileName); long remotefileSize = 0;
try
{
remotefileSize= this.GetFileSize(remoteFileName);
}
catch (Exception ex)
{
throw new IOException(string.Format("由于 {0} 导致 PutBrokenFile 出现异常",ex.Message));
} try
{
if (!File.Exists(strFileName))
{
throw new IOException(string.Format("由于 {0} 导致 PutBrokenFile 出现异常","待上传的文件不存在"));
} var fInfo = new FileInfo(strFileName);
var localFilesize = fInfo.Length;
if (localFilesize < remotefileSize)
{
throw new IOException(string.Format("由于 {0} 导致 PutBrokenFile 出现异常", "本地文件小于服务器文件 ,不能再断点上传"));
}
}
catch (Exception ex)
{
throw new IOException(string.Format("由于 {0} 导致 PutBrokenFile 出现异常", ex.Message));
} Socket socketData = CreateDataSocket();
if (Path.GetExtension(strFileName) == "")
SendCommand("APPE " + Path.GetFileNameWithoutExtension(strFileName));
else
SendCommand("APPE " + Path.GetFileName(strFileName)); if (!(_iReplyCode == 125 || _iReplyCode == 150))
{
throw new IOException(_strReply.Substring(4));
} FileStream input = new FileStream(strFileName, FileMode.Open);
input.Seek(remotefileSize, SeekOrigin.Begin);
int iBytes = 0;
while ((iBytes = input.Read(_buffer, 0, _buffer.Length)) > 0)
{
socketData.Send(_buffer, iBytes, 0);
}
input.Close();
if (socketData.Connected)
{
socketData.Close();
}
if (!(_iReplyCode == 226 || _iReplyCode == 250))
{
ReadReply();
if (!(_iReplyCode == 226 || _iReplyCode == 250))
{
throw new IOException(_strReply.Substring(4));
}
}
} /// <summary>
/// 上传一个文件 ,智能判断是重新上传或者断点续传
/// 1、当ftp服务器文件不存在,或者大小等于0, 重新下载
/// 2、当ftp服务器文件存在, size>0 and size<totalsize, 断点续传
/// </summary>
/// <param name="localFileName">localfile with fullname</param>
/// <param name="remoteFileName">remote file name </param>
public void PutFileByRestartOrBroken(string localFileName, string remoteFileName = "")
{
remoteFileName = RegetFileName(localFileName, remoteFileName);
long remoteFileSize = 0;
long localFileSize = 0;
try
{
remoteFileSize = this.GetFileSize(remoteFileName);
}
catch (Exception ex)
{
remoteFileSize = 0;
} if (File.Exists(localFileName))
{
FileInfo fInfo = new FileInfo(localFileName);
localFileSize = fInfo.Length;
}
else
{
localFileSize = 0;
} if (remoteFileSize == 0)
{
this.Put(localFileName);
}
else
{
this.PutBrokenFile(localFileName, remoteFileName);
}
} private static string RegetFileName(string strFileName, string strNullOrNo)
{
string rtnString = "";
if (string.IsNullOrEmpty(strNullOrNo))
{
if (Path.GetExtension(strFileName) == "")
{
rtnString = Path.GetFileNameWithoutExtension(strFileName);
}
else
{
rtnString = Path.GetFileName(strFileName);
}
}
else
{
rtnString = strNullOrNo;
}
return rtnString;
} /// <summary>
/// 上传一个文件
/// </summary>
/// <param name="strFileName">本地文件名</param>
public void PutByGuid(string strFileName, string strGuid)
{
if (!_bConnected)
{
Connect();
}
string str = strFileName.Substring(0, strFileName.LastIndexOf("\\"));
string strTypeName = strFileName.Substring(strFileName.LastIndexOf("."));
strGuid = str + "\\" + strGuid;
System.IO.File.Copy(strFileName, strGuid);
System.IO.File.SetAttributes(strGuid, System.IO.FileAttributes.Normal);
Socket socketData = CreateDataSocket();
SendCommand("STOR " + Path.GetFileName(strGuid));
if (!(_iReplyCode == 125 || _iReplyCode == 150))
{
throw new IOException(_strReply.Substring(4));
}
FileStream input = new FileStream(strGuid, FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.Read);
int iBytes = 0;
while ((iBytes = input.Read(_buffer, 0, _buffer.Length)) > 0)
{
socketData.Send(_buffer, iBytes, 0);
}
input.Close();
File.Delete(strGuid);
if (socketData.Connected)
{
socketData.Close();
}
if (!(_iReplyCode == 226 || _iReplyCode == 250))
{
ReadReply();
if (!(_iReplyCode == 226 || _iReplyCode == 250))
{
throw new IOException(_strReply.Substring(4));
}
}
}
#endregion #region 目录操作
/// <summary>
/// 创建目录
/// </summary>
/// <param name="strDirName">目录名</param>
public void MkDir(string strDirName)
{
if (!_bConnected)
{
Connect();
}
SendCommand("MKD " + strDirName);
if (_iReplyCode != 257)
{
throw new IOException(_strReply.Substring(4));
}
} /// <summary>
/// 删除目录
/// </summary>
/// <param name="strDirName">目录名</param>
public void RmDir(string strDirName)
{
if (!_bConnected)
{
Connect();
}
SendCommand("RMD " + strDirName);
if (_iReplyCode != 250)
{
throw new IOException(_strReply.Substring(4));
}
} /// <summary>
/// 改变目录
/// </summary>
/// <param name="strDirName">新的工作目录名</param>
public void ChDir(string strDirName)
{
if (strDirName.Equals(".") || strDirName.Equals(""))
{
return;
}
if (!_bConnected)
{
Connect();
}
SendCommand("CWD " + strDirName);
if (_iReplyCode != 250)
{
throw new IOException(_strReply.Substring(4));
}
this._strRemotePath = strDirName;
}
#endregion #region 内部函数
/// <summary>
/// 将一行应答字符串记录在strReply和strMsg,应答码记录在iReplyCode
/// </summary>
private void ReadReply()
{
_strMsg = "";
_strReply = ReadLine();
_iReplyCode = Int32.Parse(_strReply.Substring(0, 3));
} /// <summary>
/// 建立进行数据连接的socket
/// </summary>
/// <returns>数据连接socket</returns>
private Socket CreateDataSocket()
{
SendCommand("PASV");
if (_iReplyCode != 227)
{
throw new IOException(_strReply.Substring(4));
}
int index1 = _strReply.IndexOf('(');
int index2 = _strReply.IndexOf(')');
string ipData = _strReply.Substring(index1 + 1, index2 - index1 - 1);
int[] parts = new int[6];
int len = ipData.Length;
int partCount = 0;
string buf = "";
for (int i = 0; i < len && partCount <= 6; i++)
{
char ch = Char.Parse(ipData.Substring(i, 1));
if (Char.IsDigit(ch))
buf += ch;
else if (ch != ',')
{
throw new IOException("Malformed PASV strReply: " + _strReply);
}
if (ch == ',' || i + 1 == len)
{
try
{
parts[partCount++] = Int32.Parse(buf);
buf = "";
}
catch (Exception)
{
throw new IOException("Malformed PASV strReply: " + _strReply);
}
}
}
string ipAddress = parts[0] + "." + parts[1] + "." + parts[2] + "." + parts[3];
int port = (parts[4] << 8) + parts[5];
Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint ep = new IPEndPoint(IPAddress.Parse(ipAddress), port);
try
{
s.Connect(ep);
}
catch (Exception)
{
throw new IOException("无法连接ftp服务器");
}
return s;
} /// <summary>
/// 关闭socket连接(用于登录以前)
/// </summary>
private void CloseSocketConnect()
{
lock (_obj)
{
if (_socketControl != null)
{
_socketControl.Close();
_socketControl = null;
}
_bConnected = false;
}
} /// <summary>
/// 读取Socket返回的所有字符串
/// </summary>
/// <returns>包含应答码的字符串行</returns>
private string ReadLine()
{
lock (_obj)
{
while (true)
{
int iBytes = _socketControl.Receive(_buffer, _buffer.Length, 0);
_strMsg += _ASCII.GetString(_buffer, 0, iBytes);
if (iBytes < _buffer.Length)
{
break;
}
}
}
char[] seperator = { '\n' };
string[] mess = _strMsg.Split(seperator);
if (_strMsg.Length > 2)
{
_strMsg = mess[mess.Length - 2];
}
else
{
_strMsg = mess[0];
}
if (!_strMsg.Substring(3, 1).Equals(" ")) //返回字符串正确的是以应答码(如220开头,后面接一空格,再接问候字符串)
{
return ReadLine();
}
return _strMsg;
} /// <summary>
/// 发送命令并获取应答码和最后一行应答字符串
/// </summary>
/// <param name="strCommand">命令</param>
public void SendCommand(String strCommand)
{
lock (_obj)
{
// Byte[] cmdBytes = Encoding.ASCII.GetBytes((strCommand + "\r\n").ToCharArray());
Byte[] cmdBytes = _ASCII.GetBytes((strCommand + "\r\n").ToCharArray());
_socketControl.Send(cmdBytes, cmdBytes.Length, 0);
Thread.Sleep(500);
ReadReply();
}
}
#endregion public void Dispose()
{
this.DisConnect();
}
}
2、 测试代码
class Program
{
static void Main(string[] args)
{
// FtpFirstTest();
// GetBrokenFileTest();
// FileSizeTest();
// FtpPutBrokenFile(); // SmartGet(); SmartPutFile(); Console.WriteLine("ftp finished");
Console.ReadKey();
} private static void FtpFirstTest()
{
var ftpServer = ConfigurationSettings.AppSettings["ftpServer"];
var ftpPort = ConfigurationSettings.AppSettings["ftpPort"];
var userName = ConfigurationSettings.AppSettings["userName"];
var pwd = ConfigurationSettings.AppSettings["pwd"]; try
{
using (var ftp = new FTPClient(ftpServer, "/", userName, pwd, int.Parse(ftpPort)))
{
if (!ftp.Connected)
{
ftp.Connect();
}
// ftp.Put("D:\\programShareFile\\[阳光电影www.ygdy8.com].44号孩子.BD.720p.中英双字幕.rmvb");
Console.WriteLine("ftp operation");
ftp.GetNoBinary("[阳光电影www.ygdy8.com].44号孩子.BD.720p.中英双字幕.rmvb", "D:\\programShareFile", "[阳光电影www.ygdy8.com].44号孩子.BD.720p.中英双字幕.rmvb");
}
}
catch (Exception ex)
{
Console.WriteLine("ftp exception msg:" + ex.Message);
}
} /// <summary>
/// 断点下载测试
/// </summary>
static void GetBrokenFileTest()
{
var ftpServer = ConfigurationSettings.AppSettings["ftpServer"];
var ftpPort = ConfigurationSettings.AppSettings["ftpPort"];
var userName = ConfigurationSettings.AppSettings["userName"];
var pwd = ConfigurationSettings.AppSettings["pwd"]; try
{
using (var ftp = new FTPClient(ftpServer, "/", userName, pwd, int.Parse(ftpPort)))
{
if (!ftp.Connected)
{
ftp.Connect();
}
//Console.WriteLine("ftp operation ing");
//ftp.Put("D:\\programShareFile\\[阳光电影www.ygdy8.com].44号孩子.BD.720p.中英双字幕.rmvb");
//Console.WriteLine("ftp operation");
var localfile = "D:\\programShareFile\\apicloudFtp.zip";
if (File.Exists(localfile))
{
FileInfo fInfo = new FileInfo(localfile);
var size = fInfo.Length;
Console.WriteLine("file now size=" + size.ToString());
ftp.GetBrokenFile("apicloudFtp.zip", "D:\\programShareFile", "apicloudFtp.zip");
}
else
{
Console.WriteLine("file not exists");
}
}
}
catch (Exception ex)
{
Console.WriteLine("ftp exception msg:" + ex.Message);
} } /// <summary>
/// 获取ftp服务器文件大小 测试。 存在的文件 ,不存在的文件
/// </summary>
static void FileSizeTest()
{
var ftpServer = ConfigurationSettings.AppSettings["ftpServer"];
var ftpPort = ConfigurationSettings.AppSettings["ftpPort"];
var userName = ConfigurationSettings.AppSettings["userName"];
var pwd = ConfigurationSettings.AppSettings["pwd"]; try
{
using (var ftp = new FTPClient(ftpServer, "/", userName, pwd, int.Parse(ftpPort)))
{
if (!ftp.Connected)
{
ftp.Connect();
}
Console.WriteLine("ftp operation");
var localfile = "D:\\programShareFile\\[阳光电影www.ygdy8.com].44号孩子.BD.720p.中英双字幕.rmvb"; var remoteFile = "[阳光电影www.ygdy8.com].44号孩子.BD.720p.中英双字幕.rmvb";
var remoteFile2 = "apicloudFtp22.zip"; try
{
var size = ftp.GetFileSize(remoteFile2);
Console.WriteLine(string.Format("file size={0}",size));
}
catch (Exception ex)
{
Console.WriteLine("ftp getfilesize exception ");
} }
}
catch (Exception ex)
{
Console.WriteLine("ftp exception msg:" + ex.Message);
}
} /// <summary>
/// 测试 ftp 断点上传
/// </summary>
static void FtpPutBrokenFile()
{
var ftpServer = ConfigurationSettings.AppSettings["ftpServer"];
var ftpPort = ConfigurationSettings.AppSettings["ftpPort"];
var userName = ConfigurationSettings.AppSettings["userName"];
var pwd = ConfigurationSettings.AppSettings["pwd"]; try
{
using (var ftp = new FTPClient(ftpServer, "/", userName, pwd, int.Parse(ftpPort)))
{
if (!ftp.Connected)
{
ftp.Connect();
}
Console.WriteLine("ftp operation");
var localfile = "D:\\programShareFile\\[阳光电影www.ygdy8.com].44号孩子.BD.720p.中英双字幕.rmvb"; var remoteFile = "apicloudFtp.zip"; try
{
ftp.PutBrokenFile(localfile, "");
}
catch (Exception ex)
{
Console.WriteLine("ftp.PutBrokenFile exception ");
}
}
}
catch (Exception ex)
{
Console.WriteLine("ftp exception msg:" + ex.Message);
}
} /// <summary>
/// 智能下载测试
/// </summary>
static void SmartGet()
{
var ftpServer = ConfigurationSettings.AppSettings["ftpServer"];
var ftpPort = ConfigurationSettings.AppSettings["ftpPort"];
var userName = ConfigurationSettings.AppSettings["userName"];
var pwd = ConfigurationSettings.AppSettings["pwd"]; try
{
using (var ftp = new FTPClient(ftpServer, "/", userName, pwd, int.Parse(ftpPort)))
{
if (!ftp.Connected)
{
ftp.Connect();
}
Console.WriteLine("ftp operation");
// var localfile = "D:\\programShareFile\\apicloudFtp.zip"; ftp.GetFileByRestartOrBroken("[阳光电影www.ygdy8.com].44号孩子.BD.720p.中英双字幕.rmvb", "D:\\programShareFile", "[阳光电影www.ygdy8.com].44号孩子.BD.720p.中英双字幕.rmvb"); }
}
catch (Exception ex)
{
Console.WriteLine("ftp exception msg:" + ex.Message);
}
} static void SmartPutFile()
{
var ftpServer = ConfigurationSettings.AppSettings["ftpServer"];
var ftpPort = ConfigurationSettings.AppSettings["ftpPort"];
var userName = ConfigurationSettings.AppSettings["userName"];
var pwd = ConfigurationSettings.AppSettings["pwd"]; try
{
using (var ftp = new FTPClient(ftpServer, "/", userName, pwd, int.Parse(ftpPort)))
{
if (!ftp.Connected)
{
ftp.Connect();
}
Console.WriteLine("ftp operation");
var localfile = "D:\\programShareFile\\[阳光电影www.ygdy8.com].44号孩子.BD.720p.中英双字幕.rmvb"; try
{
ftp.PutFileByRestartOrBroken(localfile);
}
catch (Exception ex)
{
Console.WriteLine("ftp.PutBrokenFile exception ");
}
}
}
catch (Exception ex)
{
Console.WriteLine("ftp exception msg:" + ex.Message);
}
}
}
3 config配置
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<appSettings>
<add key="ftpServer" value="127.0.0.1"/>
<add key="ftpPort" value="21"/>
<add key="userName" value="hyt"/>
<add key ="pwd" value="hyt"/>
</appSettings>
</configuration>
4 使用到 filezilla server ftp服务器。测试正常工作
5 为了更加方便的理解ftp原理,附上ftp命令和响应值文档
FTP命令字和响应码解释 FTP命令 命令 描述
ABOR 中断数据连接程序
ACCT <account> 系统特权帐号
ALLO <bytes> 为服务器上的文件存储器分配字节
APPE <filename> 添加文件到服务器同名文件
CDUP <dir path> 改变服务器上的父目录
CWD <dir path> 改变服务器上的工作目录
DELE <filename> 删除服务器上的指定文件
HELP <command> 返回指定命令信息
LIS2T <name> 如果是文件名列出文件信息,如果是目录则列出文件列表
MODE <mode> 传输模式(S=流模式,B=块模式,C=压缩模式)
MKD <directory> 在服务器上建立指定目录
NLST <directory> 列出指定目录内容
NOOP 无动作,除了来自服务器上的承认
PASS <password> 系统登录密码
PASV 请求服务器等待数据连接
PORT <address> IP 地址和两字节的端口 ID
PWD 显示当前工作目录
QUIT 从 FTP 服务器上退出登录
REIN 重新初始化登录状态连接
REST <offset> 由特定偏移量重启文件传递
RETR <filename> 从服务器上找回(复制)文件
RMD <directory> 在服务器上删除指定目录
RNFR <old path> 对旧路径重命名
RNTO <new path> 对新路径重命名
SITE <params> 由服务器提供的站点特殊参数
SMNT <pathname> 挂载指定文件结构
STAT <directory> 在当前程序或目录上返回信息
STOR <filename> 储存(复制)文件到服务器上
STOU <filename> 储存文件到服务器名称上
STRU <type> 数据结构(F=文件,R=记录,P=页面)
SYST 返回服务器使用的操作系统
TYPE <data type> 数据类型(A=ASCII,E=EBCDIC,I=binary)
USER <username>> 系统登录的用户名 FTP响应码 响应代码 解释说明
110 新文件指示器上的重启标记
120 服务器准备就绪的时间(分钟数)
125 打开数据连接,开始传输
150 打开连接
200 成功
202 命令没有执行
211 系统状态回复
212 目录状态回复
213 文件状态回复
214 帮助信息回复
215 系统类型回复
220 服务就绪
221 退出网络
225 打开数据连接
226 结束数据连接
227 进入被动模式(IP 地址、ID 端口)
230 登录因特网
250 文件行为完成
257 路径名建立
331 要求密码
332 要求帐号
350 文件行为暂停
421 服务关闭
425 无法打开数据连接
426 结束连接
450 文件不可用
451 遇到本地错误
452 磁盘空间不足
500 无效命令
501 错误参数
502 命令没有执行
503 错误指令序列
504 无效命令参数
530 未登录网络
532 存储文件需要帐号
550 文件不可用
551 不知道的页类型
552 超过存储分配
553 文件名不允许
ftp 操作,支持断点续传或者继续下载。的更多相关文章
- FTP文件上传 支持断点续传 并 打印下载进度(二) —— 单线程实现
这个就看代码,哈哈哈哈哈 需要用到的jar包是: <dependency> <groupId>commons-net</groupId> <artifact ...
- edtftpj让Java上传FTP文件支持断点续传
在用Java实现FTP上传文件功能时,特别是上传大文件的时候,可以需要这样的功能:程序在上传的过程中意外终止了,文件传了一大半,想从断掉了地方继续传:或者想做类似迅雷下载类似的功能,文件太大,今天传一 ...
- webuploader-异步切片上传(暂不支持断点续传)及 下载方法!C#/.NET
十年河东,十年河西,莫欺少年穷 学无止境,精益求精 进入正题: 关于webuploader,参考网址:https://fex.baidu.com/webuploader/: 本篇博客范例下载地址:ht ...
- C# http下载(支持断点续传)
分享下项目里面自己封装的一个http下载类 功能如下: 1.支持断点续传 2.下载失败自动重试 3.超时等异常处理 using System; using System.Collections.Gen ...
- 设置IIS7/IIS7.5的FTP支持断点续传
Windows Server 2003的IIS自带FTP默认支持断点续传,但是Windows Server 2008/R2默认已经不支持,因此需要注意设置,才能让其支持断点续传,更好的利用宝贵的服务器 ...
- php大文件下载支持断点续传
<?php /** php下载类,支持断点续传 * * Func: * download: 下载文件 * setSpeed: 设置下载速度 * getRange: ...
- 【FTP】FTP文件上传下载-支持断点续传
Jar包:apache的commons-net包: 支持断点续传 支持进度监控(有时出不来,搞不清原因) 相关知识点 编码格式: UTF-8等; 文件类型: 包括[BINARY_FILE_TYPE(常 ...
- c#上传下载ftp(支持断点续传)
using System;using System.Net;using System.IO;using System.Text;using System.Net.Sockets;namespace f ...
- Spring Boot Ftp Client 客户端示例支持断点续传
本章介绍 Spring Boot 整合 Ftpclient 的示例,支持断点续传 本项目源码下载 1 新建 Spring Boot Maven 示例工程项目 注意:是用来 IDEA 开发工具 File ...
随机推荐
- Android-Service生命周期
Service的基本概念,以及Service的生命周期: 一.Service的基本概念: 一个Service就是应用程序的组件,可以在后台长期跑,或者是为其他的应用提供功能上的支持.Service一般 ...
- Spring MVC常见的三种URL请求参数的处理
//方法1:@RequestParam //url:/test1?id=123 @RequestMapping(value = "/test1",method = RequestM ...
- PHP的OB缓存(输出缓存)
使用PHP自带的缓存机制 原则:如果ob缓存打开,则echo的数据首先放在ob缓存.如果是header信息,直接放在程序缓存.当页面执行到最后,会把ob缓存的数据放到程序缓存,然后依次返回给浏览器. ...
- access数据库连接问题
使用Visual Studio连接access数据库(数据库后缀.accdb)时连接不上(access数据库提示未在本地计算机上注册“Microsoft.ACE.OLEDB.12.0”提供程序)解决办 ...
- js之正则1
在看jquery的源码时,看到对$对象的init入口对参数解析时,正则的迷惑. 疑惑点:z = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/ a = ...
- operator
/* * 由SharpDevelop创建. * 用户: jinweijie * 日期: 2015/10/28 * 时间: 9:15 * * 要改变这种模板请点击 工具|选项|代码编写|编 ...
- STREAMS流机制
STREAMS流机制 基本概念 STREAMS(流)是系统V提供的构造内核设备驱动程序和网络协议包的一种通用方法,对STREAMS进行讨论的目的是为了理解系统V的终端接口,I/O多路转接中poll(轮 ...
- python datatime
一.datetime 1.date date.today() 2.time 3.datetime datetime.now() datetime.strftime(fmt) 转换为字符串 dateti ...
- xcode8 导入 dylib
点击 add others shift + command + g
- 新建MMS草稿保存后,再进入草稿修改收件人,退出到会话界面,会显示两条草稿
分析原因:新建彩信草稿,保存后,再打开草稿,修改收件人,再保存会产生新的threadId, 而之前保存的草稿theadId还存在,导致此问题. (必现. 解决方法:将原来的Thread_id和新的收件 ...