|
There does appear to be a problem here.
The NLST request is made, and the response comes back on the response connection, however its only read until 'some' data is receved. It should continue reading until the response code comes back on the main connection.
This seems to fix it, but Im not entirely happy using the sleep....But time was short, and I didn't have the time to do any better!
Regards Simon Sprott
public string[] GetFileList(string mask)<br />
{<br />
if ( !this.loggedin ) this.Login();<br />
<br />
Socket cSocket = createDataSocket();<br />
<br />
this.sendCommand("NLST " + mask);<br />
<br />
if(!(this.resultCode == 150 || this.resultCode == 125)) throw new FtpException(this.result.Substring(4));<br />
<br />
this.message = "";<br />
<br />
DateTime timeout = DateTime.Now.AddSeconds(this.timeoutSeconds);<br />
<br />
int respCode = 0;<br />
while( timeout > DateTime.Now && this.PeekResponse(ref respCode))<br />
{<br />
int bytes = cSocket.Receive(buffer, buffer.Length, 0);<br />
if (bytes == 0)<br />
System.Threading.Thread.Sleep(10); <br />
this.message += ASCII.GetString(buffer, 0, bytes);<br />
}<br />
string[] msg = this.message.Replace("\r","").Split('\n');<br />
<br />
cSocket.Close();<br />
<br />
if ( this.message.IndexOf( "No such file or directory" ) != -1 )<br />
msg = new string[]{};<br />
<br />
this.readResponse();<br />
<br />
if ( this.resultCode != 226 )<br />
msg = new string[]{};<br />
<br />
return msg;<br />
}<br />
<br />
private bool PeekResponse(ref int respCode)<br />
{<br />
byte[] respBuffer = new byte[3];<br />
<br />
int bytesRead = clientSocket.Receive(respBuffer, 0, 3, SocketFlags.Peek);<br />
if (bytesRead != 3)<br />
return false;<br />
<br />
string strResp = ASCII.GetString(respBuffer, 0, 3);<br />
<br />
respCode = int.Parse( strResp );<br />
return true;<br />
}<br />
<br />
-- modified at 6:14 Tuesday 11th October, 2005
|
|
|
|
|
Hi, I have the same bug, and your fix doesn't work : I have a FtpException 'No files found' at the line :
this.message = "";
(this.message = "450 No files found\r")
and I am sure there are files on my website :
Dim oFTP As New FtpClient(sServer, sUser, sPwd)
oFTP.Login()
Dim asListe$() = oFTP.GetFileList()
oFTP.Close()
|
|
|
|
|
I'm using logic similar to yours in an FTP application to download all available files in a directory on the Host server that the application logs into. I'm using the command sendCommand("NLST " + mask); (where Mask is "*.*") to get a list of files available for download. The issue I'm encountering is that all files available are not being returned in the return buffer. There are 4 files, all of which have been previously downloaded but when I try to download the files again only 1 file is being returned in the buffer as being available. Has this issue been encountered?
TMCK
|
|
|
|
|
I'm having the same problema too :S
|
|
|
|
|
The problem lies in the while loop that receives the file list from the server:
while( timeout > DateTime.Now )
{
int bytes = cSocket.Receive(buffer, buffer.Length, 0);
this.message += ASCII.GetString(buffer, 0, bytes);
if ( bytes < this.buffer.Length ) break;
}
It exits whenever the number of received bytes is less than the
size of the buffer. Change the 'break' line to:
if ( bytes == 0 ) break;
and you should see the whole directory listing.
I'm no expert for sockets and this stuff too, this is just a hack that worked
for me. I think this whole loop (and probably all similar loops within this class)
should be rewritten. (The timeout condition seems to be nonsense since the
socket is blocking.)
|
|
|
|
|
does this client have proxy support? if not then how can we go around this.
Thanks
|
|
|
|
|
|
This class will at best be extremely buggy.
It uses a fake timeout mekanism which impers the whole class.
Otherwise its ok.
In stead of this it should use
socket.SetSocketOption(SocketOptionLevel.Socket,
SocketOptionName.SendTimeout,Timeout);
socket.SetSocketOption(SocketOptionLevel.Socket,
SocketOptionName.ReceiveTimeout,Timeout);
But unfortunently this is not enough to make it work.
Al receve logick will have to be rewritten, but that should be a fearly easy task.
|
|
|
|
|
This library is just waiting for a long time in the following line of code:
this.sendCommand( "PASS " + password );
However, I was able to use plain FPT command with user id and password. Also, it worked somehow one time for me but not more.
Thanks for any help.
Alex
|
|
|
|
|
I am facing the same problem. Strangely though, when i tried to execute the code in debug mode ,going throgh each line in code, the upload worked. However if i execute using F5 it hangs.On stopping the last line in output window is 'Send PASS' which indicates that the execution hanged after this. I have tried it repeatedly and always the same result.please help.
|
|
|
|
|
connections to remote servers are not instant you know.
|
|
|
|
|
I am not sure why, but if my ftp server (IIS) has a banner message or a welcome message the FTP Client will not work. If I remove the welcome message it works fine. I think it has something to do with the ReadResponse Method.
It could be the same problem the guy in an earlier response was having with his BulletProof FTP Server.
If anyone could help it would be great!
-------
I just was doing some more debugging and I found that if I walk through all the methods using the visual studio debugger, it will work for me. This tells me that since I run the the process slower each time I hit F11, I think it has something to do with timing. I found some posts that say some guys added some sleep as follows:
Thread.Sleep(500);
clientSocket.Send( cmdBytes, cmdBytes.Length, 0);
They added this just before the line above and it fixed their problem. I tried this and I couldn't get it to work.
I hope this helps more!
-------
I finally got it. The ReadLine() method had some issues. I found a post labeled NIce Job but a few comments. That guy said the problem is with the \n character not getting put back on the message. He also posted his method that replaces the readline method. I replaced my readline method with his and now everything works perfectly.
Here is his method:
private string readLine()
{
while( true )
{
message = "";
while( true )
{
bytes = clientSocket.Receive( buffer, buffer.Length, 0 );
message += ASCII.GetString( buffer, 0, bytes );
if( bytes < buffer.Length ) break;
}
string[] msg = message.Split('\n');
int idx = msg.Length;
idx = ( idx > 2 ) ? idx - 2 : 0;
message = msg[ idx ] + "\n"; // restore the new-line character lost in Split
if( verboseDebugging ) Debug.Write( message, "FtpClient" );
if( (message.Length > 4) && message.Substring(3,1).Equals(" ") ) return message;
} // while( true ) outer loop
} // method readLine( )
Replace your readline method with his and it should fix everything for you.
Thanks All!
|
|
|
|
|
The Split its a very trouble method, sometimes the last index is "" and your idx gets trouble
After the slipt is a good ideia do clean some garbage.
string[] msg = message.Split('\n');
int idx = msg.Length;
// clean here... ignore the last empty line
if( idx > 0 && msg[idx-1].Trim().Equals( "" ) ) idx--;
I saw this problem using GetList, where the slipt returns 3 strings, and the last is empty.
Thanks for your code!
Jose Cruz
Software Developer and Architect for .NET and J2EE Technologies.
|
|
|
|
|
I also ran into this problem. The reason that the original code did not work correctly was probably because it did not handle multi-line messages correctly. My welcome message is returned as "230-Hello, Good People...". The dash indicates a multipe part message. See below FTP RFC 959...
The original Jaimon Mathew code modified as below seem to resolve the multi-line problem as well.
private bool isDone( byte []b, long read )<br />
{<br />
if ( read >= 4 <br />
&& Char.IsDigit((char)b[0]) <br />
&& Char.IsDigit((char)b[1])<br />
&& Char.IsDigit((char)b[2])<br />
&& Char.IsWhiteSpace((char)b[3])<br />
)<br />
{<br />
return true;<br />
}<br />
<br />
return false;<br />
}<br />
private string readLine()<br />
{<br />
<br />
while (true)<br />
{<br />
bytes = clientSocket.Receive(buffer, buffer.Length, 0);<br />
mes += ASCII.GetString(buffer, 0, bytes);<br />
if (bytes < buffer.Length && isDone(buffer,bytes) )<br />
{<br />
break;<br />
}<br />
}<br />
<br />
char[] seperator = {'\n'};<br />
string[] mess = mes.Split(seperator);<br />
<br />
if (mes.Length > 2)<br />
{<br />
mes = mess[mess.Length-2];<br />
} else<br />
{<br />
mes = mess[0];<br />
}<br />
<br />
if (mes.Length < 4)<br />
{<br />
mes += " Corrupt reply from ftp server, (Length < 4)";<br />
}<br />
<br />
if (debug)<br />
{<br />
for (int k=0;k < mess.Length-1;k++)<br />
{<br />
Trace.WriteLine(mess[k]);<br />
}<br />
}<br />
return mes;<br />
}<br />
Below is a quote from http://www.faqs.org/rfcs/rfc959.html[^]
"Thus the format for multi-line replies is that the first line will begin with the exact required reply code, followed immediately by a Hyphen, "-" (also known as Minus), followed by text. The last line will begin with the same code, followed immediately by Space <sp>, optionally some text, and the Telnet end-of-line code.
For example:
123-First line
Second line
234 A line beginning with numbers
123 The last line
The user-process then simply needs to search for the second occurrence of the same reply code, followed by <sp> (Space), at the beginning of a line, and ignore all intermediary lines. If an intermediary line begins with a 3-digit number, the Server must pad the front to avoid confusion."
-- modified at 13:31 Thursday 22nd September, 2005
|
|
|
|
|
I use the exact code you have here in your example, but nothing gets actually uploaded. No error, but no upload either. Any ideas? Thanks a bunch!
Other than that, seems to work fine.
|
|
|
|
|
I 've tested it in asynchro.
It works but not everytime.
-----------------------------------
string server ="XX.XXX.XXX.XXX";
string login = "FTPUSER";
string pwd = "FTPPASS";
WebCamService.FtpClient ffttpp = new WebCamService.FtpClient(server,login,pwd,1000,21);
AsyncCallback callback = new AsyncCallback(CloseConnection);
ffttpp.Login();
ffttpp.BeginDownload(source.Text,destination.Text, callback);
ffttpp.Close();
-------------------------------------
private void CloseConnection(IAsyncResult result)
{
MessageBox.Show(result.IsCompleted.ToString());
if ( ffttpp != null ) ffttpp.Close();
ffttpp = null;
}
----------------------------------------
then the file is created in the destination directory and stay at 0k volume.
it worked with a 10 Mo file but not everytime....
Help
I'd like to make a download tool, wiche could launch a download and be able in the same time to make some other search.
but it should have a progress bar,too.
Thanx to helper.
|
|
|
|
|
|
Thanks a lot for the information but I'm getting some errors with this one too so maybe you know if you had this problem.
I'm getting a SocketException: An unknows, invalid, or unsupported option or level was specified in a getsockopt or setsockopt call
Here is my code:
<br />
ftpClient1=new Melih.FTPClient.FTPClient();<br />
<br />
try<br />
{<br />
this.ftpClient1.User="Test";<br />
this.ftpClient1.Port=21;<br />
this.ftpClient1.Host="127.0.0.1";<br />
this.ftpClient1.SetPassword("AyRHjg7k");<br />
<br />
this.ftpClient1.FTPOpen();<br />
this.ftpClient1.FTPConnect();<br />
<br />
this.ftpClient1.FTPPutFile(@"C:\Tmp\x\xxx.jpg","xx.jpg",Melih.FTPClient.FileTransferType.Binary,Melih.FTPClient.DataConnectionType.Passive,Melih.FTPClient.FileTransferResuming.Resume);<br />
}<br />
<br />
catch(Melih.FTPClient.FTPClientException Exc)<br />
{<br />
MessageBox.Show("Caught Error :"+Exc.Message);<br />
}<br />
<br />
catch(System.Net.Sockets.SocketException Exc)<br />
{<br />
MessageBox.Show("Caught Error :"+Exc.Message);<br />
}<br />
<br />
finally<br />
{<br />
if(this.ftpClient1.State==Melih.FTPClient.ConnectionState.Connected)<br />
this.ftpClient1.FTPClose();<br />
}<br />
|
|
|
|
|
Well actually I was able to fix that problem by commenting 2 lines in the FTPOpen Function:
<br />
Now I'm able to connect to another server but I still can't connect to my private server, I keep getting Login or Password error and I have change this 100 times and I still get the same problem. I'm not sure if BulletProof has something for the passwords that I can't get them to work.
Thanks
|
|
|
|
|
The TimeOuts are part of the socket level, not the Tcp level
FTPSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, TimeOut);
FTPSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, TimeOut);
|
|
|
|
|
Hello,
I just downloaded this Library and im testing it with my ftp server BulletProof FTP Server v2.21 but I can't figure out why is not working propertly. My server uses passive mode.
<br />
MyApplication.FtpClient MyFtp=new FtpClient("127.0.0.1","Test","shDDLuag",10,21);<br />
<br />
<br />
try<br />
{<br />
MyFtp.Login();<br />
<br />
MyFtp.Upload(@"C:\Tmp\x\pic.jpg");<br />
MyFtp.Close();<br />
}<br />
<br />
catch(MyApplication.FtpClient.FtpException Exc)<br />
{<br />
MessageBox.Show("There was an error: "+Exc.Message.ToString());<br />
}<br />
<br />
finally<br />
{<br />
MyFtp.Close();<br />
}<br />
If anyone has any idea please let me know.
Thanks
|
|
|
|
|
Yes, it's lacking a few things, but this is the best FREE ftp class out there. Saved me a ton of work, and it was easy to modify your delegates in order to thread this thing. Plus, the socket use allowed me to easily drop in a progress bar.
Thanks!
MT
http://www.teddev.com
|
|
|
|
|
A really great work
|
|
|
|
|
Proper async support would use BeginXXX and EndXXX methods, would expose properties to monitor the status, and would support cancellation.
Unfortunately, implementation would be a bit of work, since the best approach would be to use async socket methods and a state machine to keep track of progress.
The current async support would be better off not even present, since it is a thin wrapper over what you could do with any synchronous library by using BeginInvoke with a delegate. Using BeginInvoke by hand is more flexable: at least it allows passing a user state object and handling any exceptions upon completion.
|
|
|
|
|
I like it, but how can I change file permissions using this library? I tried by using SendCommand("QUOTE SITE chmod 777
|
|
|
|
|