使用嵌套字用FTP協議進行文件上傳下載!
以下代碼使用C#完成!完成。using System;
using System.Net.Sockets;
/// <summary>
/// Ftp 的摘要說明。
/// </summary>
public class Ftp
{
public Ftp()
{
//
// TODO: 在此處添加構造函數邏輯
//
}
string _ser;
public string Server
{
set{ _ser=value;}
get{return _ser;}
}
string _port;
public string Port
{
set{_port=value;}
get{return _port;}
}
string _user;
public string User
{
set{ _user=value;}
get{return _user;}
}
string _pws;
public string Password
{
set{ _pws=value;}
get{return _pws;}
}
bool _IsLog;
public bool IsLogined
{
set{ _IsLog=value;}
get{return _IsLog;}
}
int _MsgID;
public int MsgID
{
set{ _MsgID=value;}
get{return _MsgID;}
}
System.Windows.Forms.Label _infx=new System.Windows.Forms.Label() ;
public System.Windows.Forms.Label InfsShow
{
set{_infx=value;}
get{return _infx;}
}
System.Windows.Forms.ListBox _infs=new System.Windows.Forms.ListBox();
public System.Windows.Forms.ListBox InfsList
{
set{_infs=value;}
get{return _infs;}
}
System.Windows.Forms.ProgressBar _pb=new System.Windows.Forms.ProgressBar() ;
public System.Windows.Forms.ProgressBar Progress
{
set{_pb=value;}
get{return _pb;}
}
public string NowInf;
System.Net.Sockets.TcpClient tcFtp;
NetworkStream Stm;
public bool Login()
{
try
{
SetInf("正在連接服務器...");
tcFtp=new TcpClient(_ser, System.Convert.ToInt32(_port));//連接服務器
Stm= tcFtp.GetStream();//獲取網絡流
byte[] data=new byte[255];
int bytes;
SetInf("等待服務器就緒!");
bytes=Stm.Read(data,0,data.Length);
string msg=System.Text.Encoding.ASCII.GetString(data,0,bytes);//讀取登錄成功的消息
if (msg.Substring(0,3)=="220")
{
SetInf(msg);
if (DoCmd("USER " + _user+" ","331"))
{
if (DoCmd("PASS " + _pws,"230"))
{
SetInf("服務器就緒!");
this.IsLogined=true;
return true;
}
SetInf("密碼錯誤!",230);
return false;
}
SetInf("用戶名錯誤",331);
return false;
}
else
{
SetInf("服務器沒有正確響應!",220);
return false;
}
}
catch (System.Exception ex)
{
NowInf=ex.Message ;
_infx.Text=NowInf;
return false;
}
}
/// <summary>
///
/// </summary>
/// <param name="cmd"></param>
/// <param name="wait">匹配前麵的字符就可以了</param>
/// <returns></returns>
private bool DoCmd(string cmd,string wait)
{
string msg=DoCommand(cmd);
SetInf(msg);
if (msg.IndexOf("/r/n")>=0)
{
string xx=msg.Substring(msg.IndexOf("/r/n")) ;
msg=(xx=="/r/n"?msg:xx);
msg=msg.Replace("/r/n","");
}
msg+="/r/n";
return (msg.Substring(0,wait.Length).ToLower()==wait.ToLower() );//如果msg的前部分是wait,則返回成功.
}
private bool RetOk(string s1,string s2)
{
string msg=s1;
if (msg.IndexOf("/r/n")>=0)
{
string xx=msg.Substring(msg.IndexOf("/r/n")) ;
msg=(xx=="/r/n"?msg:xx);
msg=msg.Replace("/r/n","");
}
s1=msg+"/r/n";
return (s1.Substring(0,s2.Length).ToLower()==s2.ToLower() );//如果msg的前部分是wait,則返回成功.
}
private string DoCommand(string cmd)
{
string msg=cmd;//+System.Text.Encoding.ASCII.GetString(vbnull);
byte[] data=System.Text.Encoding.ASCII.GetBytes(msg+"/r/n");
Stm.Write(data,0,data.Length);
System.Windows.Forms.Application.DoEvents();
System.Windows.Forms.Application.DoEvents();
System.Windows.Forms.Application.DoEvents();
System.Windows.Forms.Application.DoEvents();
System.Windows.Forms.Application.DoEvents();
data=new byte[255];
int bytes;
while(Stm.DataAvailable==false)
{
System.Windows.Forms.Application.DoEvents() ;
NowInf="正在等待服務器響應!";
}
bytes=Stm.Read(data,0,data.Length);
msg=System.Text.Encoding.ASCII.GetString(data,0,bytes);
return msg;
}
private void SetInf(string msg)
{
if( msg.IndexOf("/r/n")>=0)
{
msg=msg.Substring(0,msg.LastIndexOf("/r/n")-"/r/n".Length );
msg+=" "+ System.DateTime.Now.TimeOfDay.ToString();
}
NowInf=msg;
_infx.Text=NowInf;
_infs.Items.AddRange(msg.Split("/r/n".ToCharArray()));
System.Windows.Forms.Application.DoEvents();
_infs.SelectedIndex=_infs.Items.Count-1;
System.Windows.Forms.Application.DoEvents();
System.Windows.Forms.Application.DoEvents();
}
private void SetInf(string msg,int msgid)
{
SetInf(msg);
_MsgID=msgid;
}
private string GetMsg()
{
string msg;
byte[] data=new byte[1024];
int bytes;
System.Windows.Forms.Application.DoEvents();
System.Windows.Forms.Application.DoEvents();
System.Windows.Forms.Application.DoEvents();
System.Windows.Forms.Application.DoEvents();
while(Stm.DataAvailable==false)//如果沒有信息可讀,等待服務器響應.
{
System.Windows.Forms.Application.DoEvents() ;
}
bytes=Stm.Read(data,0,data.Length);//讀取數據
msg=System.Text.Encoding.ASCII.GetString(data,0,bytes);//轉換為字符
int rn= msg.IndexOf("/r/n",0);//查找換行符號
if (rn>0)
{
string mg=msg.Substring(rn);//這裏是為了防止傳輸來多行數據,我試圖加大緩衝,也是這樣.
if( mg.Length>2)//在這裏處理如同226這樣消息.
{ //前麵一次返回接受了一部分,第二次接受到了前麵的一部分,在這裏用來分開他們
mg=mg.Substring(2);
msg=mg;
}
}
SetInf(msg);
return msg;
}
/// <summary>
/// 注銷登錄
/// </summary>
/// <returns>成功時返回真</returns>
public bool Logout()
{
this.IsLogined=false;
bool ok=DoCmd("QUIT","221");
SetInf("已斷開服務器!",221);
return ok;
}
public bool SetCurDir(string Path)
{
if (DoCmd("CWD "+Path,"250")==false)//"" is current directory.
{
SetInf("確認當前目錄失敗!",257);
return false;
}
if (DoCmd("PWD "+Path,"257")==false)//"" is current directory.
{
SetInf("確認當前目錄失敗!",257);
return false;
}
return true;
}
public string GetCurDir()
{
string msg=DoCommand("PWD");
string[] st=msg.Split((char)34);
return st[1];
}
public bool Delete(string FileName)
{
return DoCmd("DELE "+FileName,"250");
}
/// <summary>
/// 上傳文件
/// </summary>
/// <param name="FileName">要上傳的本地文件</param>
/// <param name="SvrPath">服務器目標路徑.</param>
/// <returns>傳輸成功返回真.</returns>
public bool UploadFile(string FileName)
{
_pb.Value=5;
if (this.IsLogined==false)
{
SetInf("沒有連接到服務器或沒有登錄!");
return false;
}
if (DoCmd("TYPE I","200")==false)//Type set to I.
{
SetInf("執行Type i失敗!",200);
return false;
}
_pb.Value=10;
string[] pt=FileName.Split("//".ToCharArray());
string filename=pt[pt.Length-1] ;//SvrPath+"/"+pt[pt.Length-1] ;
string tmp1=DoCommand("SIZE "+ filename);
SetInf(tmp1);
if (RetOk(tmp1,"550")!=true)//50 /bbs/Dv_ForumNews/廣告.txt: No such file.
{
if (RetOk(tmp1,"501")!=true)
{
SetInf("文件已存在!",550);
return false;
}
else
{
SetInf("文件名為空,請指定文件名!",501);
return false;
}
}
_pb.Value=15;
if (DoCmd("MODE S" ,"200")==false)//Type set to I.
{
SetInf("模式設置失敗!");
//return false;
}
/////獲取傳輸文件的ip和段口
string tmp2 =DoCommand("PASV");
SetInf(tmp2);
if (RetOk(tmp2,"227")==false)//Type set to I.
{
SetInf("服務器沒有返回227,無法知道端口,也無法開始傳輸文件!",227);
return false;
}
string[] ips=GetIP( tmp2);
///////////////////
TcpClient tcm;
try
{
_pb.Value=20;
SetInf("正在連接文件傳輸服務器!");
tcm=new TcpClient(ips[0],System.Convert.ToInt32(ips[1]));//連接傳輸服務器.
}
catch (System.Exception ex1)
{
SetInf("連接文件傳輸服務器時出錯:IP地址:"+ips[0]+"端口:" + ips[1]+" 相關信息:" + ex1.Message );
return false;
}
if (DoCmd("STOR "+ filename,"150")==false)//發送傳輸文件的指令.返回應該是150,否則出錯
{
SetInf("開始傳輸文件的指令服務器響應的不是150,不知道服務器是不是準備接受文件!",150);
return false;
}
//讀取文件///////////////////////
SetInf("正在讀取文件,準備傳輸...");
System.IO.FileStream fs;
byte[] fbins;
try
{
_pb.Value=25;
fs=new System.IO.FileStream(FileName,System.IO.FileMode.Open,System.IO.FileAccess.Read);
fbins=new byte[fs.Length] ;
fs.Read(fbins,0,System.Convert.ToInt32(fs.Length));
}
catch( System.Exception ex2)
{
SetInf("文件讀取失敗,失敗原因:"+ex2.Message);
return false;
}
_pb.Value=35;
/////////////////////////////////////////////////////
NetworkStream tmx=tcm.GetStream();//獲得流
SetInf("正在向網絡數據流中寫入數據...");
_pb.Value=45;
tmx.Write(fbins,0,fbins.Length);//寫入信息
tmx=null;
tcm.Close();
_pb.Value=55;
if (RetOk(GetMsg(),"226")==false)//一般226信息為兩次 ,本次是說明磁盤目前可用大小已經使用大小
{
}
string tmp3;
_pb.Value=65;
tmp3=DoCommand("SIZE "+ filename);//獲取大小.
SetInf(tmp3);
_pb.Value=75;
if (RetOk(tmp3,"213"))//返回大小
{
SetInf("正在核對文件大小");
int ln=System.Convert.ToInt32(tmp3.Substring(4));//得到遠程文件的大小
_pb.Value=89;
if( ln==fbins.Length)//如果大小相同.說明完整傳輸.
{
SetInf("文件傳輸成功!",0);
return true;
}
SetInf("文件傳輸後文件大小不一致!",213);
return false;
}
_pb.Value=100;
SetInf("文件傳輸成功,但確認文件大小時服務器響應的不是213!因此無法保證數據傳輸是否正確!",213);
return false;
}
/// <summary>
/// 從消息裏提取用於傳輸文件的服務器地址和端口
/// </summary>
/// <param name="Inf">消息</param>
/// <returns>數組,0為ip地址,1為端口.</returns>
private string[] GetIP(string Inf)
{
string[] rt=new string[2];
if (Inf.IndexOf("(")>0 )
{
string ips=Inf.Substring( Inf.IndexOf("(")+1);
ips=ips.Substring(0,ips.IndexOf(")"));
string[] ip=ips.Split(",".ToCharArray());
rt[0]=ip[0]+"."+ip[1]+"."+ip[2]+"."+ip[3];//前麵4組byte是ip地址.
int x1=System.Convert.ToInt16(ip[4]);//ip地址
int x2=System.Convert.ToInt16(ip[5]);//端口
int rtx=x1*256+x2;//計算端口.消息裏後兩組byte是端口,前者乘256加上後者就是服務器給你的端口.
rt[1]=rtx.ToString();
}
return rt;
}
public bool DownloadFile(string SvrFileName,string SaveToFileName)
{
string FileName=SvrFileName;
if (this.IsLogined==false)
{
SetInf("沒有連接到服務器或沒有登錄!");
return false;
}
_pb.Value=5;
DoCmd("NOOP","200");
if (DoCmd("TYPE I","200")==false)//Type set to I.
{
SetInf("執行Type i失敗!",200);
return false;
}
_pb.Value=10;
DoCmd("NOOP","200");
_pb.Value=25;
if (DoCmd("MODE S" ,"200")==false)//Type set to I.
{
SetInf("模式設置失敗!",200);
//return false;
}
/////獲取傳輸文件的ip和段口
DoCmd("NOOP","200");
_pb.Value=34;
string tmp2 =DoCommand("PASV");
SetInf(tmp2);
_pb.Value=40;;
if (RetOk(tmp2,"227")==false)//Type set to I.
{
SetInf("服務器沒有返回227,無法知道端口,也無法開始傳輸文件!",227);
return false;
}
string[] ips=GetIP( tmp2);
TcpClient tcm;
try
{
_pb.Value=50;
SetInf("正在連接文件傳輸服務器!");
tcm=new TcpClient(ips[0],System.Convert.ToInt32(ips[1]));//連接傳輸服務器.
}
catch (System.Exception ex1)
{
SetInf("連接文件傳輸服務器時出錯:IP地址:"+ips[0]+"端口:" + ips[1]+" 相關信息:" + ex1.Message );
return false;
}
_pb.Value=55;
DoCmd("NOOP","200");
string inf=DoCommand("RETR "+ FileName);
if (inf.IndexOf("150")==-1)
{
SetInf(inf);
return false;
}
_pb.Value=60;
SetInf("正在準備接收文件...");
System.IO.FileStream fs;
try
{
fs=new System.IO.FileStream(SaveToFileName,System.IO.FileMode.OpenOrCreate ,System.IO.FileAccess.ReadWrite );
}
catch( System.Exception ex2)
{
SetInf("文件創建或打開失敗,失敗原因:"+ex2.Message);
return false;
}
/////////////////////////////////////////////////////
///
NetworkStream tmx=tcm.GetStream();//獲得流
_pb.Value=70;
SetInf("正在接收文件...");
int i=0;
int c=0;
do
{
byte[] dats=new byte[10240];
i=tmx.Read(dats,0,dats.Length);
c+=i;
System.Windows.Forms.Application.DoEvents();
System.Windows.Forms.Application.DoEvents();
System.Windows.Forms.Application.DoEvents();
fs.Write(dats,0,i);
System.Windows.Forms.Application.DoEvents();
System.Windows.Forms.Application.DoEvents();
System.Windows.Forms.Application.DoEvents();
this.InfsShow.Text=c+"字節已複製.";
}
while (i>0 );
c=0;
this.InfsShow.Text="正在保存文件!";
fs.Close();
tmx=null;
tcm.Close();
DoCmd("NOOP","200");
this.InfsShow.Text="";
return true;
}
}
最後更新:2017-04-02 00:06:24