27. januar 2005 - 22:07
Der er
49 kommentarer og 1 løsning
Simpel FTP Klient
Jeg ville høre om der er nogen der har en FTP Klient klasse liggende. Jeg havde tænkt mig noget lignende: public class FTPClient { //Opretter en forbindelse til FTPServeren public FTPClient(string host, string username, string password) { } //Downloader en fil eks. Download("test\\mappe\\fil.txt", "C:\\test\\fil.txt") public void Download(string serverFile, string localFile) { } //Uploader en fil eks. Upload("C:\\test\\fil.txt", "test\\mappe\\fil.txt") public void Upload(string localFile, string serverFile) { } //Opretter en mappe public void MkDir(string dirname) { } //Ændre mappe public void ChangeDir(string dirname) { } //Returnerer alle filer i mappen public string[] ListDir(string dirname) { } //Afbryder forbindelse public void Close() { } } Er der nogen der har det? Eller evt. kan bidrage med lidt info?
Annonceindlæg tema
27. januar 2005 - 22:09
#1
FTP Forbindelsen skal arbejde i en tråd, således at denne klasse kan arbejde uafhængigt af andre enheder.
27. januar 2005 - 22:10
#2
using System; using System.IO; using System.Text; using System.Net.Sockets; using System.Threading; public class FtpClient { private TcpClient ctrl; private NetworkStream ctrlstm; private TcpClient data; private NetworkStream datastm; private static void Send(NetworkStream stm, string line) { byte[] b = Encoding.Default.GetBytes(line); stm.Write(b, 0, b.Length); } private static string Receive(NetworkStream stm) { byte[] b = new byte[100000]; int ix = 0; int n; while(stm.DataAvailable) { n = stm.Read(b, ix, b.Length - ix); ix += n; } return Encoding.Default.GetString(b, 0, ix); } public static string Command(NetworkStream stm, string cmd) { Send(stm, cmd + "\r\n"); Thread.Sleep(50); return Receive(stm); } private void SetupData() { string dataaddr = Command(ctrlstm, "PASV"); string[] addrparts = dataaddr.Split("()".ToCharArray())[1].Split(",".ToCharArray()); string datahost = addrparts[0] + "." + addrparts[1] + "." + addrparts[2] + "." + addrparts[3]; int dataport = int.Parse(addrparts[4]) * 256 + int.Parse(addrparts[5]); data = new TcpClient(datahost, dataport); datastm = data.GetStream(); } public FtpClient(string host, string username, string password) { ctrl = new TcpClient(host, 21); ctrlstm = ctrl.GetStream(); Command(ctrlstm, "USER " + username); Command(ctrlstm, "PASS " + password); } public string Dir() { SetupData(); Command(ctrlstm, "LIST"); string res = Receive(datastm); Receive(ctrlstm); datastm.Close(); data.Close(); return res; } public string ShortDir() { SetupData(); Command(ctrlstm, "NLST"); string res = Receive(datastm); Receive(ctrlstm); datastm.Close(); data.Close(); return res; } public void MkDir(string dir) { Command(ctrlstm, "MKD " + dir); } public void RmDir(string dir) { Command(ctrlstm, "RMD " + dir); } public void ChDir(string dir) { Command(ctrlstm, "CWD " + dir); } public void UpLoad(string filename, bool binary) { if(binary) { Command(ctrlstm, "TYPE I"); } else { Command(ctrlstm, "TYPE A"); } SetupData(); Command(ctrlstm, "STOR " + filename); Receive(ctrlstm); FileStream f = new FileStream(filename, FileMode.Open); byte[] b = new byte[100000]; int ix = 0; int n; while(ix < f.Length) { n = f.Read(b, 0, b.Length); datastm.Write(b, 0, n); Thread.Sleep(100); ix += n; } f.Close(); datastm.Close(); data.Close(); } public void DownLoad(string filename, bool binary) { if(binary) { Command(ctrlstm, "TYPE I"); } else { Command(ctrlstm, "TYPE A"); } SetupData(); Command(ctrlstm, "RETR " + filename); Receive(ctrlstm); FileStream f = new FileStream(filename, FileMode.Create); byte[] b = new byte[100000]; int n; while(datastm.DataAvailable) { n = datastm.Read(b, 0, b.Length); f.Write(b, 0, n); Thread.Sleep(100); } f.Close(); datastm.Close(); data.Close(); } public void Logout() { Command(ctrlstm, "QUIT"); ctrlstm.Close(); ctrl.Close(); } } class TestClass { public static void Main(string[] args) { FtpClient cli = new FtpClient("localhost", "anonymous", "arne@"); Console.WriteLine(cli.ShortDir()); Console.WriteLine(cli.Dir()); Directory.SetCurrentDirectory("C:\\"); cli.DownLoad("z.zip", true); cli.MkDir("subdir"); cli.ChDir("subdir"); cli.UpLoad("z.zip", true); cli.Logout(); } }
27. januar 2005 - 22:11
#3
(jeg har lidt ekstra funktionalitet liggende i VB.NET som nemt kan backportes til C#)
27. januar 2005 - 22:12
#4
27. januar 2005 - 22:12
#5
Jeg tester lige.
27. januar 2005 - 22:20
#6
arne_v << jeg kunne godt tænke mig et par kommentarer i sourcen :)
27. januar 2005 - 22:22
#7
Når jeg benytter: Console.WriteLine(cli.ShortDir()); Console.WriteLine(cli.Dir()); Så får jeg en IndexOutOfBounds Exception.
27. januar 2005 - 22:24
#8
Sandsyneligvis fordi din login fejler
27. januar 2005 - 22:24
#9
Nej, for jeg kan sagtens: cli.MkDir("subdir");
27. januar 2005 - 22:25
#10
Hvilken del af koden er ikke umiddelbart forståelig ?
27. januar 2005 - 22:25
#11
og har tjekket på serveren. Mappen er oprettet.
27. januar 2005 - 22:26
#12
Prøv at sætte Sleep i Command metoden lidt op så f.eks. til 200
27. januar 2005 - 22:28
#14
Er det en langsom FTP server du skal have fat i ?
27. januar 2005 - 22:31
#15
Det med Sleep hjalp ikke. Jeg forsøger at connecte til en ProFTPd på en Debian maskine. Hvis jeg benytter en anden klient her på min PC så går det hurtigt.
27. januar 2005 - 22:32
#16
Det sjove med FTPFactory er at det er rimelig langsomt, og det kun er af og til at der bliver oprettet forbindelse. Meget mystisk.
27. januar 2005 - 22:35
#17
Supporterer din FTP server PASV mode ? Fordi min kode virker kun med PASV !
27. januar 2005 - 22:36
#18
Det gør den, ja.
27. januar 2005 - 22:52
#19
Så må du jo nok til at debugge lidt. public static string Command(NetworkStream stm, string cmd) { Console.WriteLine("SEND: " + cmd); Send(stm, cmd + "\r\n"); Thread.Sleep(50); string resp = Receive(stm); Console.WriteLine("RECV: " + resp); return resp; }
27. januar 2005 - 22:58
#21
arne << jeg debugger i morgen. Jeg vender tilbage. Tak for nu.
30. januar 2005 - 19:39
#22
Kommet videre ?
01. februar 2005 - 22:08
#23
Ja. Jeg kan virkelig ikke få det til at virke. Jeg har debugget og debugget. Forstår det ikke. Jeg har også prøvet sourcen fra de url du smed. En af dem (
http://www.csharphelp.com/archives/archive9.html ) kan jeg nogle gange få til at virke. Andre gange står den bare og 'hænger' jeg kan se på min ftp server at der er forbindelse men at klienten er IDLE, selvom jeg har sat den til at uploade en stor fil. Og filen findes ikke på serveren. :( I'm lost.
01. februar 2005 - 22:10
#24
Kan du copy paste outpyt fra mit 27/01-2005 22:52:46 forslag, så kan jeg muligvis sige noget ?
01. februar 2005 - 22:17
#25
SEND: USER krogh RECV: SEND: PASS ****** (Har jeg fjernet :P ) RECV: SEND: TYPE I RECV: SEND: PASV RECV: Herefter kommer følgende: Project Project12.exe encountered unhandled exception class System.IndexOutOfRangeException. Process stopped. Use Step or Run to continue.
01. februar 2005 - 22:20
#26
Jeg har lige prøvet at udfører de 4 kommandoer ved brug af telnet til ftp serveren. Der får jeg ingen fejl.
01. februar 2005 - 22:21
#27
Får du et svar ? Der er jo ikke noget svar fra serveren i ovenstående !
01. februar 2005 - 22:22
#28
Prøv: public FtpClient(string host, string username, string password) { ctrl = new TcpClient(host, 21); ctrlstm = ctrl.GetStream(); Thread.Sleep(250); Command(ctrlstm, "USER " + username); Command(ctrlstm, "PASS " + password); Thread.Sleep(250); }
01. februar 2005 - 22:25
#29
Jeg får ikke noget svar når jeg bruger sourcen, nej. Men nu oprettes forbindelsen. Hvordan tester jeg så om den kan downloade en given fil til mit drev E. F.eks. har jeg irfan.exe liggende i roden af min ftp konto.
01. februar 2005 - 22:28
#30
Directory.SetCurrentDirectory("E:\\"); cli.DownLoad("irfan.exe", true); formoder jeg
01. februar 2005 - 22:28
#31
Jeg prøvede lige at lave en: Console.WriteLine(cli.Dir()); Der fik jeg så igen min Exception.
01. februar 2005 - 22:30
#32
-- gav også samme exception.
01. februar 2005 - 22:30
#33
Hvilken Sleep tid kører du med i Command ?
01. februar 2005 - 22:33
#34
200
01. februar 2005 - 22:35
#35
Kan det hjælpe dig hvis jeg opretter en konto på min ftp server til dig?
01. februar 2005 - 22:36
#36
måske ja
01. februar 2005 - 22:39
#37
IP: 212.242.201.104 brugernavn: arne_v :: PASSWORD: dit brugernavn
01. februar 2005 - 22:41
#38
Jeg benytter desuden C#Builder Personal fra borland.
01. februar 2005 - 22:48
#39
Jeg prøver lige. Jeg har også en C#Builder installeret omend jeg ikke bruger den meget.
01. februar 2005 - 22:52
#40
Jeg kan lave en ShortDir og Dir men der ligger ingen filer ...
01. februar 2005 - 22:54
#41
Nej. Mappen er tom. FtpClient cli = new FtpClient("10.0.0.200", "arne_v", "arne_v"); Console.WriteLine(cli.ShortDir()); Console.WriteLine(cli.Dir()); Har jeg lige prøvet. Lykkes ikke for mig. Jeg får den der exception.
01. februar 2005 - 22:55
#42
Kan du evt poste den source du lige benyttede?
01. februar 2005 - 22:58
#43
Behøves ikke. Har vist fundet fejlen.
01. februar 2005 - 22:58
#44
using System; using System.IO; using System.Text; using System.Net.Sockets; using System.Threading; public class FtpClient { private TcpClient ctrl; private NetworkStream ctrlstm; private TcpClient data; private NetworkStream datastm; private static void Send(NetworkStream stm, string line) { byte[] b = Encoding.Default.GetBytes(line); stm.Write(b, 0, b.Length); } private static string Receive(NetworkStream stm) { byte[] b = new byte[100000]; int ix = 0; int n; while(stm.DataAvailable) { n = stm.Read(b, ix, b.Length - ix); ix += n; } return Encoding.Default.GetString(b, 0, ix); } public static string Command(NetworkStream stm, string cmd) { Console.WriteLine("SEND: " + cmd); Send(stm, cmd + "\r\n"); Thread.Sleep(200); string resp = Receive(stm); Console.WriteLine("RECV: " + resp); return resp; } private void SetupData() { string dataaddr = Command(ctrlstm, "PASV"); string[] addrparts = dataaddr.Split("()".ToCharArray())[1].Split(",".ToCharArray()); string datahost = addrparts[0] + "." + addrparts[1] + "." + addrparts[2] + "." + addrparts[3]; int dataport = int.Parse(addrparts[4]) * 256 + int.Parse(addrparts[5]); data = new TcpClient(datahost, dataport); datastm = data.GetStream(); } public FtpClient(string host, string username, string password) { ctrl = new TcpClient(host, 21); ctrlstm = ctrl.GetStream(); Command(ctrlstm, "USER " + username); Command(ctrlstm, "PASS " + password); } public string Dir() { SetupData(); Command(ctrlstm, "LIST"); string res = Receive(datastm); Receive(ctrlstm); datastm.Close(); data.Close(); return res; } public string ShortDir() { SetupData(); Command(ctrlstm, "NLST"); string res = Receive(datastm); Receive(ctrlstm); datastm.Close(); data.Close(); return res; } public void MkDir(string dir) { Command(ctrlstm, "MKD " + dir); } public void RmDir(string dir) { Command(ctrlstm, "RMD " + dir); } public void ChDir(string dir) { Command(ctrlstm, "CWD " + dir); } public void UpLoad(string filename, bool binary) { if(binary) { Command(ctrlstm, "TYPE I"); } else { Command(ctrlstm, "TYPE A"); } SetupData(); Command(ctrlstm, "STOR " + filename); Receive(ctrlstm); FileStream f = new FileStream(filename, FileMode.Open); byte[] b = new byte[100000]; int ix = 0; int n; while(ix < f.Length) { n = f.Read(b, 0, b.Length); datastm.Write(b, 0, n); Thread.Sleep(100); ix += n; } f.Close(); datastm.Close(); data.Close(); } public void DownLoad(string filename, bool binary) { if(binary) { Command(ctrlstm, "TYPE I"); } else { Command(ctrlstm, "TYPE A"); } SetupData(); Command(ctrlstm, "RETR " + filename); Receive(ctrlstm); FileStream f = new FileStream(filename, FileMode.Create); byte[] b = new byte[100000]; int n; while(datastm.DataAvailable) { n = datastm.Read(b, 0, b.Length); f.Write(b, 0, n); Thread.Sleep(100); } f.Close(); datastm.Close(); data.Close(); } public void Logout() { Command(ctrlstm, "QUIT"); ctrlstm.Close(); ctrl.Close(); } } class TestClass { public static void Main(string[] args) { FtpClient cli = new FtpClient("212.242.201.104", "arne_v", "arne_v"); Console.WriteLine(cli.ShortDir()); Console.WriteLine(cli.Dir()); cli.Logout(); } }
01. februar 2005 - 22:59
#45
SEND: USER arne_v RECV: 220 ProFTPD 1.2.5rc1 Server (Net4all.dk) [net4all] 331 Password required for arne_v. SEND: PASS arne_v RECV: 230 User arne_v logged in. SEND: PASV RECV: 227 Entering Passive Mode (212,242,201,104,108,24) SEND: NLST RECV: 550 No files found. SEND: PASV RECV: 227 Entering Passive Mode (212,242,201,104,108,25) SEND: LIST RECV: 150 Opening ASCII mode data connection for file list 226-Transfer complete. 226 Quotas off SEND: QUIT RECV: 221 Goodbye.
01. februar 2005 - 22:59
#46
OK - så du har også hul igennem nu ?
01. februar 2005 - 23:01
#47
Jep. Jeg prøvede bare for sjov at bruge min eksterne IP i stedet for min interne. Jeg kan kun bruge min eksterne. (Dog har jeg lige forsøgt med et FTP program at benytte den interne ip, det lykkes fint). Smid et svar - du fortjener point :)
01. februar 2005 - 23:02
#48
ok
01. februar 2005 - 23:04
#49
Jeg skal understrege at min kode er ikke production quality. Den viser hvordan man gør. Diverse fejl håndtering skal ligges ind for at den bliver robust.
01. februar 2005 - 23:05
#50
Jep. Bl.a. hvis man forsøger at hente / sende en fil der ikke findes :) Tak for hjælpen.
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.