天天看點

使用嵌套字用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);

   }

   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;

       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();

   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()));

   _infs.selectedindex=_infs.items.count-1;

  private void setinf(string msg,int msgid)

   setinf(msg);

   _msgid=msgid;

  private string getmsg()

   string msg;

   byte[] data=new byte[1024];

   while(stm.dataavailable==false)//如果沒有資訊可讀,等待伺服器響應.  

   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;

  /// 登出登入

  /// <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);

   if (docmd("pwd "+path,"257")==false)//"" is current directory.

   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");

  /// 上傳檔案

  /// <param name="filename">要上傳的本地檔案</param>

  /// <param name="svrpath">伺服器目标路徑.</param>

  /// <returns>傳輸成功傳回真.</returns>

  public bool uploadfile(string filename)

   _pb.value=5;

   if (this.islogined==false)

    setinf("沒有連接配接到伺服器或沒有登入!");

   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;  

     setinf("檔案名為空,請指定檔案名!",501);

   _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);

   string[] ips=getip( tmp2);

   ///////////////////

   tcpclient tcm;

    _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 );

   if (docmd("stor "+ filename,"150")==false)//發送傳輸檔案的指令.傳回應該是150,否則出錯

    setinf("開始傳輸檔案的指令伺服器響應的不是150,不知道伺服器是不是準備接受檔案!",150);

   //讀取檔案///////////////////////

   setinf("正在讀取檔案,準備傳輸...");

   system.io.filestream fs;

   byte[] fbins;

    _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);

   _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);

   _pb.value=100;

   setinf("檔案傳輸成功,但确認檔案大小時伺服器響應的不是213!是以無法保證資料傳輸是否正确!",213);

   return false;

  /// 從消息裡提取用于傳輸檔案的伺服器位址和端口

  /// <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;

   docmd("noop","200");

   _pb.value=25;

    setinf("模式設定失敗!",200);

   _pb.value=34;

    _pb.value=40;;

    _pb.value=50;

   string inf=docommand("retr "+ filename);

   if (inf.indexof("150")==-1)

    setinf(inf);

    _pb.value=60;

   setinf("正在準備接收檔案...");

    fs=new system.io.filestream(savetofilename,system.io.filemode.openorcreate ,system.io.fileaccess.readwrite );

    setinf("檔案建立或打開失敗,失敗原因:"+ex2.message);

   ///

   _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();

    fs.write(dats,0,i);

    this.infsshow.text=c+"位元組已複制.";

   while (i>0 );

   c=0;

   this.infsshow.text="正在儲存檔案!";

   fs.close();

   this.infsshow.text="";

}