using Microsoft.VisualBasic;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
namespace clsFTP1
{
public class clsFTP
{
#region "Class Variable Declarations"
private string m_sRemoteHost, m_sRemotePath, m_sRemoteUser;
private string m_sRemotePassword, m_sMessk;
private int m_iRemotePort, m_iBytes;
private Socket m_objClientSocket;
private Int32 m_iRetValue;
private bool m_bLoggedIn;
private string m_sMes, m_sReply;
//设置用户来对FTP服务器读取和写入数据的数据包的大小
//对下列具体大小
public const int BLOCK_SIZE = 512;
private byte[] m_aBuffer= new byte[BLOCK_SIZE];
private Encoding ASCII = Encoding.ASCII;
public bool flag_bool;
//普通变量定义
private string m_sMessageString;
#endregion
#region "Class Constructors"
//Main类构造器
public clsFTP()
{
m_sRemoteHost = "localhost";
m_sRemotePath = ".";
m_sRemoteUser = "anonymous";
m_sRemotePassword = "";
m_sMessageString = "";
m_iRemotePort = 21;
m_bLoggedIn = false;
}
//参数化的构造器
public clsFTP(string sRemoteHost,string sRemotePath,string sRemoteUser,string sRemotePassword,int iRemotePort)
{
m_sRemoteHost = sRemoteHost;
m_sRemotePath = sRemotePath;
m_sRemoteUser = sRemoteUser;
m_sRemotePassword = sRemotePassword;
m_sMessageString = "";
m_iRemotePort = 21;
m_bLoggedIn = false;
}
#endregion
#region "Public Properties"
//设置或得到你想链接的FTP服务器的名称
public string RemoteHostFTPServer
{
//得到FTP服务器的名称
get
{
return m_sRemoteHost;
}
}
//设置或得到你想链接的FTP服务器的FTP端口
public int RemotePort
{
//得到FTP端口号
get
{
return m_iRemotePort;
}
set
{
m_iRemotePort = value;
}
}
//设置或得到你想链接的FTP服务器的远程路径
public string RemotePath
{
//得到的远程路径
get
{
return m_sRemotePath;
}
set
{
m_sRemotePath = value;
}
}
//设置你想链接的远程FTP服务器的密码
public string RemotePassword
{
get
{
return m_sRemotePassword;
}
set
{
m_sRemotePassword = value;
}
}
//设置或得到你想链接远程的FTP服务器的用户
public string RemoteUser
{
get
{
return m_sRemoteUser;
}
set
{
m_sRemoteUser = value;
}
}
//设置messagestring类
public string MessageString
{
get
{
return m_sMessageString;
}
set
{
m_sMessageString = value;
}
}
#endregion
#region "Public Functions"
//从文件系统中返回一个文件列表。在string()函数中返回文件。
public string[] GetFileList(string sMask)
{
Socket cSocket;
Int32 bytes;
Char seperator = ControlChars.Lf;
string[] mess;
m_sMes = "";
//检查你是否登录到FTP服务器上
if(!m_bLoggedIn)
{
Login();
}
cSocket = CreateDataSocket();
//发送FTP命令
SendCommand("NLST " + sMask);
if(!(m_iRetValue == 150 || m_iRetValue == 125))
{
MessageString = m_sReply;
throw new IOException(m_sReply.Substring(4));
}
m_sMes = "";
while (true)
{
Array.Clear(m_aBuffer, 0, m_aBuffer.Length);
bytes = cSocket.Receive(m_aBuffer, m_aBuffer.Length, 0);
m_sMes += ASCII.GetString(m_aBuffer, 0, bytes);
if (bytes < m_aBuffer.Length)
break;
}
mess = m_sMes.Split(seperator);
cSocket.Close();
ReadReply();
if(m_iRetValue != 226)
{
MessageString = m_sReply;
throw new IOException(m_sReply.Substring(4));
}
return mess;
}
//得到FTP服务器上的文件大小
public long GetFileSize(string sFileName)
{
long size;
if (!m_bLoggedIn)
Login();
//发送一个FTP命令
SendCommand("SIZE " + sFileName);
size = 0;
if (m_iRetValue == 213)
{
size = Int64.Parse(m_sReply.Substring(4));
}
else
{
MessageString = m_sReply;
throw new IOException(m_sReply.Substring(4));
}
return size;
}
//登录FTP服务器
private bool Login()
{
m_objClientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint ep = new IPEndPoint(Dns.Resolve(m_sRemoteHost).AddressList[0], m_iRemotePort);
try
{
m_objClientSocket.Connect(ep);
}
catch(Exception ex)
{
MessageString = m_sReply;
throw new IOException("Cannot connect to the remote server");
}
ReadReply();
if (m_iRetValue != 220)
{
CloseConnection();
MessageString = m_sReply;
throw new IOException(m_sReply.Substring(4));
}
//为了发送一个对服务器的用户登录ID,发送一个FTP命令
SendCommand("USER " + m_sRemoteUser);
if(!(m_iRetValue == 331 || m_iRetValue == 230))
{
Cleanup();
MessageString = m_sReply;
throw new IOException(m_sReply.Substring(4));
}
if(m_iRetValue!=230)
{
//为了发送一个对服务器的用户密码,发送一个FTP命令
SendCommand("PASS " + m_sRemotePassword);
if(!(m_iRetValue == 230 || m_iRetValue == 202))
{
Cleanup();
MessageString = m_sReply;
throw new IOException(m_sReply.Substring(4));
}
}
m_bLoggedIn = true;
//为了改变映射的远程服务器的文件夹的目录,调用用户定义的ChangeDirectory函数
ChangeDirectory(m_sRemotePath);
//返回最终结果
return m_bLoggedIn;
}
//如果模式值为真,对下载设置为二进制模式。否则,设置为ASCII模式
public void SetBinaryMode(bool bMode)
{
if (bMode)
//发送FTP命令,设置为二进制模式
//(TYPE是一种用作说明请求类型的FTP命令.)
SendCommand("TYPE I");
else
{
//发送FTP命令,设置ASCII模式。
//(TYPE是一种用作说明请求类型的FTP命令。)
SendCommand("TYPE A");
}
if (m_iRetValue != 200)
{
MessageString = m_sReply;
throw new IOException(m_sReply.Substring(4));
}
}
//向一个配置好的本地文件夹下载一个远程文件。保持文件名一样。
public void DownloadFile(string sFileName,bool bResume)
{
DownloadFile(sFileName, "", bResume);
}
//地文件名下载一个远程文件。你必须包含一个路径。
//本地文件名将会创建或者将会被重写,但是路径必须存在。
public void DownloadFile(string sFileName,string sLocalFileName)
{
DownloadFile(sFileName, sLocalFileName, false);
}
//对一个本地文件名下载一个远程文件。你必须包含一个路径。设置恢复标志。本地文件名将会被创建或被重写,但是本地路径必须存在。
public void DownloadFile(string sFileName, string sLocalFileName,bool bResume)
{
Stream st;
FileStream output;
Socket cSocket;
long offset, npos;
if (!m_bLoggedIn)
Login();
SetBinaryMode(true);
if(sLocalFileName.Equals(""))
{
sLocalFileName = sFileName;
}
if (!(File.Exists(sLocalFileName)))
{
st = File.Create(sLocalFileName);
st.Close();
}
output = new FileStream(sLocalFileName, FileMode.Open);
cSocket = CreateDataSocket();
offset = 0;
if (bResume)
{
offset = output.Length;
if (offset > 0)
{
//发送一个FTP命令重新启动
SendCommand("REST " + offset);
if (m_iRetValue != 350)
offset = 0;
}
if (offset > 0)
npos = output.Seek(offset, SeekOrigin.Begin);
}
//发送一个FTP命令重新找到一个文件。
SendCommand("RETR " + sFileName);
if(!(m_iRetValue == 150 || m_iRetValue == 125))
{
MessageString = m_sReply;
throw new IOException(m_sReply.Substring(4));
}
while(true)
{
Array.Clear(m_aBuffer, 0, m_aBuffer.Length);
m_iBytes = cSocket.Receive(m_aBuffer, m_aBuffer.Length, 0);
output.Write(m_aBuffer, 0, m_iBytes);
if (m_iBytes <= 0)
break;
}
output.Close();
if (cSocket.Connected)
cSocket.Close();
ReadReply();
if(!(m_iRetValue == 226 || m_iRetValue == 250))
{
MessageString = m_sReply;
throw new IOException(m_sReply.Substring(4));
}
}
//这是一个从你的本地硬盘上向你的FTP文件夹中上载文件的函数
public void UploadFile(string sFileName)
{
UploadFile(sFileName, false);
}
//这是一个从你的本地硬盘上向你的FTP网页上上载的函数和设置恢复标志
public void UploadFile(string sFileName,bool bResume)
{
Socket cSocket;
long offset;
FileStream input;
bool bFileNotFound;
if (!m_bLoggedIn)
Login();
cSocket = CreateDataSocket();
offset = 0;
if(bResume)
{
try
{
SetBinaryMode(true);
offset = GetFileSize(sFileName);
}
catch(Exception ex)
{
offset = 0;
}
}
if(offset>0)
{
SendCommand("REST " + offset);
if (m_iRetValue != 350)
//远程服务器可能不支持恢复。
offset = 0;
}
//发送一个FTP命令,存储一个文件。
SendCommand("STOR " + Path.GetFileName(sFileName));
if(!(m_iRetValue == 125 || m_iRetValue == 150))
{
MessageString = m_sReply;
throw new IOException(m_sReply.Substring(4));
}
//在上载之前,检查文件是否存在。
bFileNotFound = false;
if(File.Exists(sFileName))
{
//打开输入流读取源文件
input = new FileStream(sFileName, FileMode.Open);
if (offset != 0)
input.Seek(offset, SeekOrigin.Begin);
//上载这个文件
m_iBytes = input.Read(m_aBuffer, 0, m_aBuffer.Length);
while (m_iBytes > 0)
{
cSocket.Send(m_aBuffer, m_iBytes, 0);
m_iBytes = input.Read(m_aBuffer, 0, m_aBuffer.Length);
}
input.Close();
}
else
{
bFileNotFound = true;
}
if (cSocket.Connected)
cSocket.Close();
//如果找不到文件,检查返回值
if(bFileNotFound)
{
MessageString = m_sReply;
throw new IOException("The file: " + sFileName + " was not found. " +
"Cannot upload the file to the FTP site");
}
ReadReply();
if(!(m_iRetValue == 226 || m_iRetValue == 250))
{
MessageString = m_sReply;
throw new IOException(m_sReply.Substring(4));
}
}
//从远程FTP服务器上删除一个文件。
public bool DeleteFile(string sFileName)
{
bool bResult;
bResult = true;
if (!m_bLoggedIn)
Login();
//发送一个FTP命令,删除一个文件。
SendCommand("DELE " + sFileName);
if (m_iRetValue != 250)
{
bResult = false;
MessageString = m_sReply;
}
// 返回最终结果
return bResult;
}
//在远程FTP服务器上重命名一个文件
public bool RenameFile(string sOldFileName,string sNewFileName)
{
bool bResult;
bResult = true;
if (!m_bLoggedIn)
Login();
//发送一个FTP命令,对一个文件重命名
SendCommand("RNFR " + sOldFileName);
if(m_iRetValue!=350)
{
MessageString = m_sReply;
throw new IOException(m_sReply.Substring(4));
}
//发送一个FTP命令,对一个文件更改为新名称
//如果新的文件名存在,会被覆盖。
SendCommand("RNTO " + sNewFileName);
if(m_iRetValue != 250)
{
MessageString = m_sReply;
throw new IOException(m_sReply.Substring(4));
}
return bResult;
}
//这是一个在远程服务器上创建目录的函数
public bool CreateDirectory(string sDirName)
{
bool bResult;
bResult = true;
if (!m_bLoggedIn)
Login();
//发送一个FTP命令,在FTP服务器上制作一个目录
SendCommand("MKD " + sDirName);
if(m_iRetValue != 257)
{
bResult = false;
MessageString = m_sReply;
}
//返回最终结果
return bResult;
}
//这是一个在远程FTP服务器上删除目录的函数
public bool RemoveDirectory(string sDirName)
{
bool bResult;
bResult = true;
//检查是否已登录FTP服务器
if (!m_bLoggedIn)
Login();
// 发送一个FTP命令,删除在FTP服务器上的目录
SendCommand("RMD " + sDirName);
if (m_iRetValue != 250)
{
bResult = false;
MessageString = m_sReply;
}
//返回最终结果
return bResult;
}
//这是一个用来在远程FTP服务器上改变当前工作目录的函数。
public bool ChangeDirectory(string sDirName)
{
bool bResult;
bResult = true;
// 检查你是否在根目录
if ((sDirName.Equals(".")))
return bResult;
// 检查是否已登录FTP服务器
if ((!(m_bLoggedIn)))
Login();
// 发送FTP命令,改变在FTP服务器上的目录。
SendCommand("CWD " + sDirName);
if ((m_iRetValue != 250))
{
bResult = false;
MessageString = m_sReply;
}
this.m_sRemotePath = sDirName;
// 返回最终结果
return bResult;
}
//关闭远程服务器的FTP链接
public void CloseConnection()
{
if (!(m_objClientSocket == null))
//发送一个FTP命令,结束FTP服务系统。
SendCommand("QUIT");
Cleanup();
}
#endregion
#region "Private Functions"
//从FTP服务器得到回应。
private void ReadReply()
{
m_sMes = "";
m_sReply = ReadLine();
m_iRetValue = Int32.Parse(m_sReply.Substring(0, 3));
}
//清除一些变量
private void Cleanup()
{
if(!(m_objClientSocket==null))
{
m_objClientSocket.Close();
m_objClientSocket = null;
}
m_bLoggedIn = false;
}
//从FTP服务器读取一行。
private string ReadLine(bool bClearMes=false)
{
Char seperator = ControlChars.Lf;
string[] mess;
if (bClearMes)
m_sMes = "";
while(true)
{
m_aBuffer.Clear(m_aBuffer, 0, BLOCK_SIZE);
m_iBytes = m_objClientSocket.Receive(m_aBuffer, m_aBuffer.Length, 0);
m_sMes += ASCII.GetString(m_aBuffer, 0, m_iBytes);
if (m_iBytes < m_aBuffer.Length)
break;
}
mess = m_sMes.Split(seperator);
if (m_sMes.Length > 2)
m_sMes = mess[mess.Length - 2];
else
m_sMes = mess[0];
if(!(m_sMes.Substring(3, 1).Equals(" ")))
return ReadLine(true);
return m_sMes;
}
//这是一个你想链接的FTP服务器用于发送命令的函数。
private void SendCommand(string sCommand)
{
sCommand = sCommand + ControlChars.CrLf;
byte[] cmdbytes = ASCII.GetBytes(sCommand);
m_objClientSocket.Send(cmdbytes, cmdbytes.Length, 0);
ReadReply();
}
//创建一个数据包
private Socket CreateDataSocket()
{
Int32 index1, index2, len;
Int32 partCount, i, port;
string ipData, buf, ipAddress;
Int32[] parts = new Int32[6];
char ch;
Socket s;
IPEndPoint ep;
//发送一个FTP命令,用于被动数据链接
SendCommand("PASV");
if (m_iRetValue != 227)
{
MessageString = m_sReply;
throw new IOException(m_sReply.Substring(4));
}
index1 = m_sReply.IndexOf("(");
index2 = m_sReply.IndexOf(")");
ipData = m_sReply.Substring(index1 + 1, index2 - index1 - 1);
len = ipData.Length;
partCount = 0;
buf = "";
for (i = 0; i <= (len - 1) && partCount <= 6; i++)
{
ch = Char.Parse(ipData.Substring(i, 1));
if (Char.IsDigit(ch))
buf += ch;
else if (ch != ',')
{
MessageString = m_sReply;
throw new IOException("Malformed PASV reply: " + m_sReply);
}
if ((ch == ',') || (i + 1 == len))
{
try
{
parts[partCount] = Int32.Parse(buf);
partCount += 1;
buf = "";
}
catch(Exception ex)
{
MessageString = m_sReply;
throw new IOException("Malformed PASV reply: " + m_sReply);
}
}
}
ipAddress = parts[0] + "." + parts[1] + "." + parts[2] + "." + parts[3];
//在Visual Basic .Net 2002中进行调用。你想移动8位。在Visual Basic .NET 2002中,你必须将此数乘2的8次方。
//端口=parts(4)*(2^8)
//进行这个调用,并且用Visual Basic .NET 2003解释当前行。
port = parts[4] << 8;
//确定数据端口数
port = port + parts[5];
s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
ep = new IPEndPoint(Dns.Resolve(ipAddress).AddressList[0], port);
try
{
s.Connect(ep);
}
catch(Exception ex)
{
MessageString = m_sReply;
throw new IOException("Cannot connect to remote server.");
//如果你不能链接到特定的FTP服务器,也就是说,将其布尔值设置为false。
flag_bool = false;
}
//如果你能够链接到特定的FTP服务器,将布尔值设置为true。
flag_bool = true;
return s;
}
#endregion
}
}