1. win10自帶的IIS建立的FTP怎麼改為utf8編碼
IIS是WEB服務,並不會影響FTP,也和系統自帶的FTP服務無關,系統的FTP使用時,在FTP客戶端可以自行選擇GBK編碼正常連接。
2. win7打開ftp站點文件夾是亂碼
解決方法:1、Serv-U 7 以後的版本默認的編碼是UTF-8 ,而大部分Windows客戶端不支持。
2、打開Serv-U 8.0控制台,點擊「限制和設置」——「為域配置高級FTP命令設置和行為」,在FTP設置中找到OPTS UTF8命令,右擊禁用此命令。再點擊下面的「全局屬性」,在出來的FTP命令屬性選項卡中,「高級選項」里,把「對所有收發的路徑和文件名使用UFT-8編碼」前面的鉤去掉。這樣就沒有中文亂碼問題了。
3、如果是Serv-U 7 的版本,找到「限制和設置」然後點擊「為域配置高級FTP命令和行為」 ,在「為域配置高級FTP命令和行為」設置界面里點擊「FTP設置」下面的「用戶定製設置」,再點擊「全局屬性...」按鈕,會彈出全局屬性設置窗口,選擇「高級選項」,可以看到編碼的設置。將「對所有已收發的路徑和文件名使用UTF-8編碼」前的鉤去掉即可。
3. FTP recv接收文件丟失,總是接收的文件不完整,代碼如下,求指導!
file.Write(buf_recv,len);其中的len應該是你接收的實際數據的長度,不是你緩沖區的長度。最後應該關閉文件。
4. 如何解決部分FTP站點打開出現亂碼的故障
ftp站點出現亂碼,可以參考如下兩種方法解決 :
方法一:用「資源管理器」窗口打開
右擊「開始」菜單,選擇「資源管理器」菜單項
打開「資源管理器」窗口。接著,把窗口地址欄後的內容清空,輸入要打開的FTP站點回車
在彈出的對話框中輸入相應的用戶名和密碼,回車後即可打開該站點,這樣就不會出現亂碼了
方法二:使用「UTF-8」編碼
用IE瀏覽器打開那個出現亂碼的FTP站點
在彈出的對話框輸入相應的用戶名和密碼,回車後打開該站點,這時的頁面出現亂碼。
接著,依次單擊IE瀏覽器的「查看-編碼-其他」菜單項,選擇「Unicode(UTF-8)」編碼後,頁面即可恢復正常顯示了。
5. FTP命令。
命令格式:ftp [-v][-d][-i][-n][-g][-s:filename][-a][-w:windowsize][computer]
說說他們的含義吧。
-v 不顯示遠程伺服器響應
-n 禁止第一次連接的時候自動登陸
-i 在多個文件傳輸期間關閉交互提示
-d 允許調試、顯示客戶機和伺服器之間傳遞的全部ftp命令
-g 不允許使用文件名通配符,文件名通配符的意思是說允許在本地文件以及路徑名中使用通配字元
-s:filename 指定包含ftp命令的文本文件。在ftp命令啟動後將自動運行這些命令。在加的參數里不能有空格。
-a 綁定數據連接時,使用任何的本地埠
-w:windowsize 忽略默認的4096傳輸緩沖區
computer 指定要連接的遠程計算機的ip地址
1) ?
說明:顯示ftp命令的說明。後面可以加參數,是加需要解釋的命令名,不加則顯示包含所有命令列表。
2) !
說明:功能是在本地計算機上運行指定命令。
如! command 其中command就是你要運行的命令,如果不加command這個參數的話,則顯示本地命令提示, 這時你輸入exit命令就能返回到ftp了。
3)$ macro-ame[args]
說明:執行宏定義macro-name。
4) append
說明:使用當前文件類型設置,將本地文件附加到遠程計算機中。大概格式是append local-file [remote-file] 其中local-file是說指定要添加的本地文件。remote-file是說指定要將local-file附加到遠程計算機文件,要是省了這個,則是使用本地文件名做遠程文件名。
5)account[password]
說明:提供登錄遠程系統成功後訪問系統資源所需的補充口令。
6)ascii
說明:默認情況下,將文件傳輸類型設置為ASCII
7)bell
說明:響玲開關,意思是文件傳輸完成後是否有玲聲提醒。默認是關閉的。
8)binary
說明:將文件傳輸類型設置為二進制。
9)bye
說明:結束和遠程計算機的ftp會話,也就是安全斷開,退出ftp.
10)cd
說明:更改遠程計算機上的工作目錄。
如cd data 其中data是要進入的遠程計算機的目錄。
12)cp
說明:進入遠程主機目錄的父目錄。
13)chmod modefile-name
說明:將遠程主機文件file-name的存取方式設置為mode。
如 chmod 777 a.out。
14)cr
說明:使用asscii方式傳輸文件時,將回車換行轉換為回行。
15)close
說明:結束與遠程伺服器的ftp會話,並返回命令解釋程序。
16)dir
說明:顯示遠程的文件以及子目錄列表。
如dir data local-file其中data是指定要查看列表的目錄,沒指定的話就是當前目錄。local-file是指定要保存列表的本地文件,不指定的話就在屏幕輸出。
17)debug
說明:調試開關,打開的時候列印每個發送到遠程計算機的命令,命令前有——>默認情況是關閉的。
18)disconnnect
說明:與遠程計算機斷開連接,但還保持著ftp命令提示符。
19)delete remote-file
說明:刪除遠程主機文件。
20)disconnection
說明:同close。
21)form format
說明:將文件傳輸方式設置為format,預設為file方式。
22)get
說明:使用當前文件傳輸類型,把遠程的文件拷貝到本地計算機上。
如get remote-file local-fileremote-file是指定要復制的文件,local-file是指定本地計算機上的文件名,沒有指定的話則個remote-file同名。
23)glob
說明:文件名通配開關
24)hash
說明:轉換每個傳輸數據快的散列標記列印(#).數據快的大小是2048位元組。默認情況下是關閉的,
25)help
說明:顯示ftp命令的解釋,如help commmand 其中command就是你要解釋的命令,如果不加command這個參數的話就會顯示所有命令的列表
26)idle[seconds]
說明:將遠程伺服器的休眠計時器設為[seconds]秒。
27)image
說明:設置二進制傳輸方式(同binary)
28)lcd
說明:更改本地計算機的本地目錄,在默認的時候是啟動ftp的目錄.這個不要覺得沒用啊,在你使用ftp的時候為了傳遞文件不是常改變本地和遠程計算機的目錄嗎?
如lcd [directory] 其中[directory]是指定要進入的本地計算機的目錄,如果你不加這個參數,就會顯示出本地計算機的工作目錄.
29)literal
說明:向遠程ftp伺服器發送協商參數,報告.
如lireral argument [...] 其中argument是指定要發送給遠程伺服器的協商參數。
30)ls
說明:顯示遠程目錄的文件和字目錄.
如ls remote-directory local-file其中remote-directory是指要查看的列表的目錄,不指定的話顯示的是當前工作目錄。local-file是指定要保存列表的本地文件.不指定的話是在屏幕上輸出.
還有啊,寫不下了。
6. 各位高手ftp如何使用
FTP命令大全
FTP:文件傳輸協議。先說說他的功能吧,主要就是從運行FTP伺服器的計算機傳輸文件。可以交互使用。這里要注意,只有安裝了tcp/ip協議的機器才能使用ftp命令。
命令格式:ftp [-v][-d][-i][-n][-g][-s:filename][-a][-w:windowsize][computer]
說說他們的含義吧。
-v 不顯示遠程伺服器響應
-n 禁止第一次連接的時候自動登陸
-i 在多個文件傳輸期間關閉交互提示
-d 允許調試、顯示客戶機和伺服器之間傳遞的全部ftp命令
-g 不允許使用文件名通配符,文件名通配符的意思是說允許在本地文件以及路徑名中使用通配字元
-s:filename 指定包含ftp命令的文本文件。在ftp命令啟動後將自動運行這些命令。在加的參數里不能有空格。
-a 綁定數據連接時,使用任何的本地埠
-w:windowsize 忽略默認的4096傳輸緩沖區
computer 指定要連接的遠程計算機的ip地址
呵呵,理解了上面的,就說說一些具體的命令,我個人覺得雖然現在工具用起來很方便了,但懂這些命令在很多地方還是很有用的,就像現在nt下的命令提示符
1) ?
說明:顯示ftp命令的說明。後面可以加參數,是加需要解釋的命令名,不加則顯示包含所有命令列表。
2) append
說明:使用當前文件類型設置,將本地文件附加到遠程計算機中。大概格式是
append local-file [remote-file] 其中local-file是說指定要添加的本地文件。
remote-file是說指定要將local-file附加到遠程計算機文件,要是省了這個,則是使用本地文件名做遠程文件名。
3)ascii
說明:默認情況下,將文件傳輸類型設置為ASCII
4)bell
說明:響玲開關,意思是文件傳輸完成後是否有玲聲提醒。默認是關閉的。
5)binary
說明:將文件傳輸類型設置為二進制。
6)bye
說明:結束和遠程計算機的ftp會話,也就是安全斷開,退出ftp.
7)cd
說明:更改遠程計算機上的工作目錄。如cd data 其中data是要進入的遠程計算機的目錄。
8)close
說明:結束與遠程伺服器的ftp會話,並返回命令解釋程序。
9)dir
說明:顯示遠程的文件以及子目錄列表。如dir data local-file
其中data是指定要查看列表的目錄,沒指定的話就是當前目錄。local-file是指定要保存列表的本地文件,不指定的話就在屏幕輸出。
10)debug
說明:調試開關,打開的時候列印每個發送到遠程計算機的命令,命令前有——>
默認情況是關閉的。
11)disconnnect
說明:與遠程計算機斷開連接,但還保持著ftp命令提示符。
12)get
說明:使用當前文件傳輸類型,把遠程的文件拷貝到本地計算機上。
如get remote-file local-file
remote-file是指定要復制的文件,local-file是指定本地計算機上的文件名,
沒有指定的話則個remote-file同名。
13)glob
說明:文件名通配開關
14)hash
說明:轉換每個傳輸數據快的散列標記列印(#).數據快的大小是2048位元組。默認情況下是關閉的,
15)help
說明:顯示ftp命令的解釋,如help commmand 其中command就是你要解釋的命令,如果不加command這個參數的話就會顯示所有命令的列表
16)!
說明:這個命令差點忘記了:)功能是在本地計算機上運行指定命令。如! command 其中command就是你要運行的命令,如果不加command這個參數的話,則顯示本地命令提示, 這時你輸入exit命令就能返回到ftp了。
17)lcd
說明:更改本地計算機的本地目錄,在默認的時候是啟動ftp的目錄.這個不要覺得沒用啊,在你使用ftp的時候為了傳遞文件不是常改變本地和遠程計算機的目錄嗎?:)
如lcd [directory] 其中[directory]是指定要進入的本地計算機的目錄,如果你不加這個參數,就會顯示出本地計算機的工作目錄.
18)literal
說明:向遠程ftp伺服器發送協商參數,報告.
如lireral argument [...] 其中argument是指定要發送給遠程伺服器的協商參數。
19)ls
說明:顯示遠程目錄的文件和字目錄.
如ls remote-directory local-file
其中remote-directory是指要查看的列表的目錄,不指定的話顯示的是當前工作目錄。local-file是指定要保存列表的本地文件.不指定的話是在屏幕上輸出.
20)mdelete
說明:刪除遠程計算機上的文件.如mdelete remote-file ...
remote-file肯定是要刪的文件啊,可以刪除多個.
21)mdir
說明:顯示遠程目錄的文件和子目錄列表,他允許指定多個文件.
如mdir remote-file ... local-file
參數我想大家應該明白什麼意思吧?不明白就看看前面的類似命令吧.
22)mget
說明:使用當前文件傳輸類型將多個遠程文件復制到本地計算機.
如mget remote-files ...
其實remote-files可以指定多個,他就是指定要復制到本地計算機的遠程文件.
23)mkdir
說明:創建遠程目錄.
如mkdir directory 這個命令和nt下的命令提示符中的md directory一樣,不多說了.
24)mls
說明:顯示遠程目錄的文件和目錄簡表
如mls remote-file ... local-file
其中remote-file這個參數是必須要加的,』』-』』是使用遠程計算機的當前工作目錄.
25)mput
說明:使用當前文件傳輸類型,將本地文件復制到遠程計算機.
如mput local-files ...
26)open
說明:連接到指定ftp伺服器上,
如open computer port 其中computer一般是遠程計算機的ip地址,port不用說就是指定埠了。
27)prompt
說明:轉換提示,在多個文件傳輸的時候,ftp提示可以有選擇的檢索或保存文件,如果關閉提示,則mget和mput命令傳輸所有文件,在默認情況下是打開的.
28)put
說明:使用當前文件傳輸類型將本地文件復制到遠程計算機中,
如put local-file remote-file
其中local-file是指定要復制的本地文件,
remote-file是指定要復制的遠程計算機上的文件名,不指定的話是和本地計算機上的文件名同名.
29)pwd
說明:顯示遠程呢感計算機上的當前目錄.
30)quit
說明:結束與遠程計算機的ftp會話,並退出ftp.
31)quote
說明:向遠程ftp伺服器發送協議,報告.期待ftp單碼應答,這個命令的功能和literal相同.
32)recv
說明:使用當前文件傳輸類型將遠程文件復制到本地計算機,他與get命令作用相同。
33)remotehelp
說明:顯示遠程命令的幫助.這個命令的用法和help,!一樣可以參考他的用法.
34)rename
說明:更改遠程計算機上的文件名。
這個命令和nt的命令提示符的ren一樣,如rename filename newfilename
35)rmdir
說明:刪除遠程目錄.
這個命令和nt的命令提示符的rm一樣,如rmdir directory
36)send
說明:使用當前文件傳輸類型將本地文件復制到遠程計算機.send和put命令的功能一樣。
如send local-file remote-file
37)status
說明:顯示ftp連接和轉換的當前狀態
38)trace
說明:轉換報文跟蹤,運行ftp的命令時,trace將顯示沒個報文的理由。
39)type
說明:設置或顯示文件傳輸類型.
如type [type-name]
其中type-name 的意思是文件傳輸的類型,默認是ASCII,沒加這個參數就是顯示當前的傳輸類型.
40)user
說明:指定連接到遠程計算機的用戶.
如user user-name [passwd] [account]
其中user-name不用說都是用來登陸計算機的用戶名了,
passwd是指定user-name的密碼,不指定的話ftp會提示輸入密碼。
account是指定用來登陸計算機的帳號,如不指定,ftp會提示輸入帳號.
41)verbose
說明:轉換冗餘模式。這里如果打開,會顯示所有ftp響應,文件傳輸結束的時候會顯示傳輸的效率和統計信息,默認的情況是打開的.
呵呵,命令就介紹這些了,可以自己熟悉一下,其實現在ftp的軟體很多,很方便,但你說這些命令沒用也是不可能的,就像windows下一樣還保留著命令提示符.:)_ 特別有些時候ftp軟體很多地方做不到的,.? 什麼地方。
打個比方,我看過一種覓名ftp用戶得到admin的入侵列子,就的用到他.呵呵,這里不多說了,就寫到這里了。
7. 為什麼用瀏覽器訪問自己架設的FTP中文幾乎都亂碼
1、打開Serv-U 控制台,點擊「限制和設置」--「為域配置高級FTP命令設置和行為」。
2、在FTP設置中找到OPTS UTF8命令,右擊禁用此命令。
3、點擊下面的「全局屬性」。
4、在出來的FTP命令屬性選項卡中,「高級選項」里,把「對所有收發的路徑和文件名使用UFT-8編碼」前面的鉤去掉!
5、以後再上傳中文文件,就不會出現亂碼問題啦。
FTP 是File Transfer Protocol(文件傳輸協議)的英文簡稱,而中文簡稱為「文傳協議」。用於Internet上的控制文件的雙向傳輸。同時,它也是一個應用程序(Application)。基於不同的操作系統有不同的FTP應用程序,而所有這些應用程序都遵守同一種協議以傳輸文件。在FTP的使用當中,用戶經常遇到兩個概念:"下載"(Download)和"上傳"(Upload)。"下載"文件就是從遠程主機拷貝文件至自己的計算機上;"上傳"文件就是將文件從自己的計算機中拷貝至遠程主機上。用Internet語言來說,用戶可通過客戶機程序向(從)遠程主機上傳(下載)文件。
8. 訪問ftp文件 出現亂碼怎麼辦
1、打開Serv-U 8.0控制台,點擊限制和設為域配置高級FTP命令設置和行為,在FTP設置中找到OPTS UTF8命令,右擊禁用此命令。再點擊下面的全局屬性;
9. 關於如何實現FTP上傳或者下載帶進度和速率的實現方法
在這里需要說明的是,該方式是通過其他代碼進行改進的。 首先我們需要定義一個委託,用來實現傳輸過程中傳遞文件的總數,已完成的位元組數和速度,方便客戶端界面上調用。 public delegate void TransferProcess(long total,long finished,double speed); 調用代碼就不舉例了 接下來我們建立一個FTPClient類,該類基於socket和FTP協議實現了連接FTP服務,建立目錄,上傳文件,下載文件等主要方法。結構如下: 需要注意的是,我們需要定一個事件event TransferProcess OnTransferProcess;該事件在實例化FTPClient之後需要調用,這個事件對實現進度條和速率是非常重要的。為了實現速率我們還需要定義個公開的成員startTime(開始時間)。我們現在主要是看一下如何上傳的。 /// /// 上傳一個文件 /// /// 本地文件名 public void Put(string strFileName) { //連接伺服器 if (!bConnected) { Connect(); } UpdateStatus = true; //建立socket連接 Socket socketData = CreateDataSocket(); //向FTP伺服器發生存儲命令 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; long total = input.Length;//該成員主要記錄文件的總位元組數,注意這里使用長整型,是為了突破只能傳輸2G左右的文件的限制 long finished = 0;//該成員主要記錄已經傳輸完成的位元組數,注意這里使用長整型,是為了突破只能傳輸2G左右的文件的限制 double speed = 0;//記錄傳輸的速率 while ((iBytes = input.Read(buffer, 0, buffer.Length)) > 0)//循環從本地數據流中讀取數據到緩沖區 { //Console.WriteLine(startTime.ToString()); socketData.Send(buffer, iBytes, 0);//將緩沖區的數據發送到FTP伺服器 DateTime endTime = DateTime.Now;//每次發送數據的結束時間 TimeSpan ts = endTime - startTime;//計算每次發送數據的時間間隔 finished += iBytes;//計算完成的位元組數. Console.WriteLine(ts.Milliseconds); //計算速率,注意finished是位元組,所以需要換算沖K位元組 if (ts.Milliseconds > 0) { speed = (double)(finished / ts.TotalMilliseconds); speed = Math.Round(speed * 1000 / 1024, 2); } //這里是必不可少的,否則你無法實現進度條 //如果傳輸進度事件被實例化,而且從本地數據流中讀取數據不是空的並完成的位元組數也不為空的話,則實現委託. if (OnTransferProcess != null&&iBytes>0&&finished>0) { OnTransferProcess(total, finished,speed); } } UpdateStatus = false; finished = 0; input.Close();//當傳輸完成之後需要關閉數據流,以便下次訪問. if (socketData.Connected) { socketData.Close();//關閉當前的socket } if (!(iReplyCode == 226 || iReplyCode == 250)) { ReadReply(); if (!(iReplyCode == 226 || iReplyCode == 250)) { UpdateStatus = false; throw new IOException(strReply.Substring(4)); } } } 上面代碼中注釋寫得比較詳細,這里就不再一一講解了,關於下載中實現進度條和速率的問題可以參考以上代碼進行修改. 完整的代碼如下: using System; using System.net; using System.IO; using System.Text; using System.net.Sockets; namespace MMSEncoder { public delegate void TransferProcess(long total,long finished,double speed); /// /// FTP Client /// public class FTPClient { public event TransferProcess OnTransferProcess; public bool UpdateStatus = true; public DateTime startTime; private bool IsAbortConnect = false; #region 構造函數 /// /// 預設構造函數 /// public FTPClient() { strRemoteHost = ""; strRemotePath = ""; strRemoteUser = ""; strRemotePass = ""; strRemotePort = 21; bConnected = false; } /// /// 構造函數 /// /// FTP伺服器IP地址 /// 當前伺服器目錄 /// 登錄用戶賬號 /// 登錄用戶密碼 /// FTP伺服器埠 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 登陸欄位、屬性 /// /// FTP伺服器IP地址 /// private string strRemoteHost; public string RemoteHost { get { return strRemoteHost; } set { strRemoteHost = value; } } /// /// FTP伺服器埠 /// private int strRemotePort; public int RemotePort { get { return strRemotePort; } set { strRemotePort = value; } } /// /// 當前伺服器目錄 /// private string strRemotePath; public string RemotePath { get { return strRemotePath; } set { strRemotePath = value; } } /// /// 登錄用戶賬號 /// private string strRemoteUser; public string RemoteUser { set { strRemoteUser = value; } } /// /// 用戶登錄密碼 /// private string strRemotePass; public string RemotePass { set { strRemotePass = value; } } /// /// 是否登錄 /// private Boolean bConnected; public bool Connected { get { return bConnected; } } #endregion #region 鏈接 /// /// 建立連接 /// public void Connect() { //if (IsAbortConnect) throw new IOException("用戶強制終止了FTP"); 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("無法連接到遠程伺服器!"); } // 獲取應答碼 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; // 切換到初始目錄 if (!string.IsNullOrEmpty(strRemotePath)) { ChDir(strRemotePath); } } /// /// 關閉連接 /// public void DisConnect() { if (socketControl != null) { SendCommand("QUIT"); } CloseSocketConnect(); } public void AbortConnect() { if (socketControl != null) { SendCommand("ABOR"); } IsAbortConnect = true; //CloseSocketConnect(); } #endregion #region 傳輸模式 /// /// 傳輸模式:二進制類型、ASCII類型 /// public enum TransferType { Binary, ASCII }; /// /// 設置傳輸模式 /// /// 傳輸模式 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; } } /// /// 獲得傳輸模式 /// /// 傳輸模式 public TransferType GetTransferType() { return trType; } #endregion #region 文件操作 /// /// 獲得文件列表 /// /// 文件名的匹配字元串 /// public string[] Dir(string strMask) { // 建立鏈接 if (!bConnected) { Connect(); } //建立進行數據連接的socket Socket socketData = CreateDataSocket(); //傳送命令 SendCommand("NLST " + strMask); //分析應答代碼 if (!(iReplyCode == 150 || iReplyCode == 125 || iReplyCode == 226)) { throw new IOException(strReply.Substring(4)); } //獲得結果 strMsg = ""; while (true) { int iBytes = socketData.Receive(buffer, buffer.Length, 0); strMsg += GB2312.GetString(buffer, 0, iBytes); if (iBytes < buffer.Length) { break; } } char[] seperator = { '
' }; string[] strsFileList = strMsg.Split(seperator); socketData.Close();//數據socket關閉時也會有返回碼 if (iReplyCode != 226) { ReadReply(); if (iReplyCode != 226) { throw new IOException(strReply.Substring(4)); } } return strsFileList; } /// /// 獲取文件大小 /// /// 文件名 /// 文件大小 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; } /// /// 刪除 /// /// 待刪除文件名 public void Delete(string strFileName) { if (!bConnected) { Connect(); } SendCommand("DELE " + strFileName); if (iReplyCode != 250) { throw new IOException(strReply.Substring(4)); } } /// /// 重命名(如果新文件名與已有文件重名,將覆蓋已有文件) /// /// 舊文件名 /// 新文件名 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 上傳和下載 /// /// 下載一批文件 /// /// 文件名的匹配字元串 /// 本地目錄(不得以\結束) public void Get(string strFileNameMask, string strFolder) { if (!bConnected) { Connect(); } string[] strFiles = Dir(strFileNameMask); foreach (string strFile in strFiles) { if (!strFile.Equals(""))//一般來說strFiles的最後一個元素可能是空字元串 { if (strFile.LastIndexOf(".") > -1) { Get(strFile.Replace("\r", ""), strFolder, strFile.Replace("\r", "")); } } } } /// /// 下載一個文件 /// /// 要下載的文件名 /// 本地目錄(不得以\結束) /// 保存在本地時的文件名 public void Get(string strRemoteFileName, string strFolder, string strLocalFileName) { if (!bConnected) { Connect(); } SetTransferType(TransferType.Binary); if (strLocalFileName.Equals("")) { strLocalFileName = strRemoteFileName; } if (!File.Exists(strLocalFileName)) { Stream st = File.Create(strLocalFileName); st.Close(); } FileStream output = new FileStream(strFolder + "\\" + strLocalFileName, FileMode.Create); Socket socketData = CreateDataSocket(); 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)); } } } /// /// 上傳一批文件 /// /// 本地目錄(不得以\結束) /// 文件名匹配字元(可以包含*和?) public void Put(string strFolder, string strFileNameMask) { string[] strFiles = Directory.GetFiles(strFolder, strFileNameMask); foreach (string strFile in strFiles) { //strFile是完整的文件名(包含路徑) Put(strFile); } } /// /// 上傳一個文件 /// /// 本地文件名 public void Put(string strFileName) { if (!bConnected) { Connect(); } UpdateStatus = true; Socket socketData = CreateDataSocket(); 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; long total = input.Length; long finished = 0; //DateTime startTime = DateTime.Now; double speed = 0; while ((iBytes = input.Read(buffer, 0, buffer.Length)) > 0) { Console.WriteLine(startTime.ToString()); socketData.Send(buffer, iBytes, 0); DateTime endTime = DateTime.Now; TimeSpan ts = endTime - startTime; finished += iBytes; Console.WriteLine(ts.Milliseconds); if (ts.Milliseconds > 0) { speed = (double)(finished / ts.TotalMilliseconds); speed = Math.Round(speed * 1000 / 1024, 2); } if (OnTransferProcess != null&&iBytes>0&&finished>0) { OnTransferProcess(total, finished,speed); } } UpdateStatus = false; finished = 0; input.Close(); if (socketData.Connected) { socketData.Close(); } if (!(iReplyCode == 226 || iReplyCode == 250)) { ReadReply(); if (!(iReplyCode == 226 || iReplyCode == 250)) { UpdateStatus = false; throw new IOException(strReply.Substring(4)); } } } #endregion #region 目錄操作 /// /// 創建目錄 /// /// 目錄名 public void MkDir(string strDirName) { if (!bConnected) { Connect(); } SendCommand("MKD " + strDirName); if (iReplyCode != 257) { throw new IOException(strReply.Substring(4)); } } /// /// 刪除目錄 /// /// 目錄名 public void RmDir(string strDirName) { if (!bConnected) { Connect(); } SendCommand("RMD " + strDirName); if (iReplyCode != 250) { throw new IOException(strReply.Substring(4)); } } /// /// 改變目錄 /// /// 新的工作目錄名 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 內部變數 /// /// 伺服器返回的應答信息(包含應答碼) /// private string strMsg; /// /// 伺服器返回的應答信息(包含應答碼) /// private string strReply; /// /// 伺服器返回的應答碼 /// private int iReplyCode; /// /// 進行控制連接的socket /// private Socket socketControl; /// /// 傳輸模式 /// private TransferType trType; /// /// 接收和發送數據的緩沖區 /// private static int BLOCK_SIZE = Int16.MaxValue; Byte[] buffer = new Byte[BLOCK_SIZE]; /// /// 編碼方式(為防止出現中文亂碼採用 GB2312編碼方式) /// Encoding GB2312 = Encoding.Default ;//Encoding.GetEncoding("gb2312"); #endregion #region 內部函數 /// /// 將一行應答字元串記錄在strReply和strMsg /// 應答碼記錄在iReplyCode /// private void ReadReply() { strMsg = ""; strReply = ReadLine(); iReplyCode = Int32.Parse(strReply.Substring(0, 3)); } /// /// 建立進行數據連接的socket /// /// 數據連接socket 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("無法連接伺服器"); } return s; } /// /// 關閉socket連接(用於登錄以前) /// private void CloseSocketConnect() { if (socketControl != null) { socketControl.Close(); socketControl = null; } bConnected = false; } /// /// 讀取Socket返回的所有字元串 /// /// 包含應答碼的字元串列 private string ReadLine() { while (true) { int iBytes = socketControl.Receive(buffer, buffer.Length, 0); strMsg += GB2312.GetString(buffer, 0, iBytes); if (iBytes < buffer.Length) { break; } } char[] seperator = { '
' }; string[] mess = strMsg.Split(seperator); if (strMsg.Length > 2) { strMsg = mess[mess.Length - 2]; //seperator[0]是10,換行符是由13和0組成的,分隔後10後面雖沒有字元串, //但也會分配為空字元串給後面(也是最後一個)字元串數組, //所以最後一個mess是沒用的空字元串 //但為什麼不直接取mess[0],因為只有最後一行字元串應答碼與信息之間有空格 } else { strMsg = mess[0]; } if (!strMsg.Substring(3, 1).Equals(" "))//返回字元串正確的是以應答碼(如220開頭,後面接一空格,再接問候字元串) { return ReadLine(); } return strMsg; } /// /// 發送命令並獲取應答碼和最後一行應答字元串 /// /// 命令 private void SendCommand(String strCommand) { Byte[] cmdBytes = GB2312.GetBytes((strCommand + "\r
").ToCharArray()); socketControl.Send(cmdBytes, cmdBytes.Length, 0); ReadReply(); } #endregion } }