VB.NET - Issues with VB.NET FTP Class to UNIX FTP Server

C

craig.overton

All,

I am currently developing an FTP class in VB.NET. It's kid tested,
mother approved when trying to access an FTP Server on a Windows box
meaning I can connect, run commands, upload and download a file no
problem. My issues come when I try to use the same class with the same
commands to access an FTP server on a UNIX box. I can connect and login
just fine, but after that all my commands come back "500 'PWD': command
not understood.". Has anyone experienced this error and can help me
solve it. In order to help everyone out the following is my class:

Imports System
Imports System.Net
Imports System.IO
Imports System.Text
Imports System.Text.ASCIIEncoding
Imports System.Net.Sockets
Imports System.Configuration
Imports System.Resources

Public Class FTPClient

#Region "Local Properties"

'''<summary>
''' Public Property: Host - String variable.
'''</summary>
Public Property Host() As String
Get
Return _Host
End Get
Set(ByVal Value As String)
_Host = Value
End Set
End Property

'''<summary>
''' Public Property: Path - String variable.
'''</summary>
Public Property Path() As String
Get
Return _Path
End Get
Set(ByVal Value As String)
_Path = Value
End Set
End Property

'''<summary>
''' Public Property: User - String variable.
'''</summary>
Public Property User() As String
Get
Return _User
End Get
Set(ByVal Value As String)
_User = Value
End Set
End Property

'''<summary>
''' Public Property: Password - String variable.
'''</summary>
Public Property Password() As String
Get
Return _Password
End Get
Set(ByVal Value As String)
_Password = Value
End Set
End Property

'''<summary>
''' Public Property: Port - String variable.
'''</summary>
Public Property Port() As String
Get
Return _Port
End Get
Set(ByVal Value As String)
_Port = Value
End Set
End Property

'''<summary>
''' Public ReadOnly Property: ResponseCode - String variable.
'''</summary>
Public ReadOnly Property ResponseCode() As String
Get
Return _ResponseCode
End Get
End Property

'''<summary>
''' Public ReadOnly Property: ResponseData - String variable.
'''</summary>
Public ReadOnly Property ResponseData() As String
Get
Return _ResponseData
End Get
End Property

#End Region

' FTP Default Properties.
Private _Host As String = "127.0.0.1"
Private _Path As String = "."
Private _User As String = "anonymous"
Private _Password As String = "(e-mail address removed)"
Private _Port As Integer = 21
Private _ResponseCode As Integer
Private _ResponseData As String
Private _FTPCommandSocket As Socket = Nothing
Private _FTPLogin As Boolean = False

#Region "Public Methods"

Public Sub New()

End Sub

'''<summary>
''' Public Function: Login - This function will create a command
and data socket and then send the
''' login credentials to the FTP host.
'''</summary>
'''<returns>Function returns a Boolean.</returns>
Public Function Login() As Boolean

' Create an FTP command socket.
CreateCommandSocket()

' Send the gathered login information to the FTP host.
Try
SendCommand("USER", _User)
SendCommand("PASS", _Password)
_FTPLogin = True
Catch ex As Exception
' Login did not work because the FTP login information was
not accepted.
_ResponseData = "FTP Login function not executed."
' Throw New MPException(AppSettings.Item("Project"),
"MP.IT.Web.Library.FTP - FTP login information was not accepted", ex)
Return False
End Try

' Login successful.
Return True

End Function

'''<summary>
''' Public Sub: Logout - This subroutine will disconnect and close
an FTP command and data socket.
'''</summary>
'''<returns>Subroutine returns nothing.</returns>
Public Sub Logout()

' Close and destroy the FTP command socket.
If (_FTPCommandSocket Is Nothing = False) Then
SendCommand("QUIT", "")
_FTPCommandSocket.Close()
_FTPCommandSocket = Nothing
End If
End Sub

'''<summary>
''' Public Sub: SendCommand - Provided a Command and Arguements,
this subroutine will execute an FTP Command.
''' Commands already taken care of with subroutines below:
''' TYPE: Mode (ASCII or Binary)
''' NLST: List files in directory
''' SIZE: Get file Size
''' RETR: Download a file
''' STOR: Upload a file
''' DELE: Delete a file
''' RNFR: Select a file to be renamed
''' RNTO: Rename a selected file
''' PWD: Get a current directory
''' CWD: Change directory
''' RDM: Remove a directory
'''</summary>
'''<param name="FTPCommand">As String</param>
'''<param name="FTPCommandArguements">As String</param>
'''<returns>Function returns an FTP stream.</returns>
Public Sub SendCommand(ByVal FTPCommand As String, ByVal
FTPCommandArguments As String)

' Combine FTP command with the FTP command arguements.
Dim _FTPCommand As String = FTPCommand & " " &
FTPCommandArguments
_FTPCommand += Environment.NewLine

' Convert the FTP command into ASCII text.
Dim commandBytes() As Byte = ASCII.GetBytes(_FTPCommand)

Try
' Execute the FTP command on the FTP host.
_FTPCommandSocket.Send(commandBytes, commandBytes.Length,
0)
ReadResponse()
Catch ex As Exception
' Command was not executed.
_ResponseData = "FTP SendCommand subroutine not executed."
' Throw New MPException(AppSettings.Item("Project"),
"MP.IT.Web.Library.FTP - FTP command was not accepted", ex)
End Try
End Sub

'''<summary>
''' Public Sub: SetBinaryMode - This subroutine sets the FTP mode
to binary.
'''<param name="mode">As Boolean</param>
'''<returns>Subroutine returns nothing.</returns>
Public Sub SetBinaryMode(ByVal mode As Boolean)

If (mode) Then
'Send the FTP TYPE command as binary.
SendCommand("TYPE ", "I")
Else
'Send the FTP TYPE command as ASCII.
SendCommand("TYPE ", "A")
End If
End Sub

'''<summary>
''' Public Function: GetDirectoryFileList - This function will get
the names of the files from the provided directory name.
'''</summary>
'''<param name="directoryName">As String</param>
'''<returns>Function returns a string.</returns>
Public Function GetFileList(ByVal directoryName As String) As
String()

' Check to see if user is logged into FTP host.
If Not _FTPLogin Then
Login()
End If

' Create an FTP data socket.
Dim _FTPDataSocket As Socket = CreateDataSocket()

'Send an FTP NLST command.
SendCommand("NLST ", directoryName)

Const _EndLine As Char = "\n"
Const _BufferSize As Integer = 512

Dim _Data As String = ""
Dim _Buffer(_BufferSize) As Byte
Dim _BytesRead As Integer = 0

If _FTPDataSocket.Connected Then
While (True)
Array.Clear(_Buffer, 0, _BufferSize)
_BytesRead = _FTPDataSocket.Receive(_Buffer,
_Buffer.Length, 0)
_Data += ASCII.GetString(_Buffer, 0, _BytesRead)

If (_BytesRead < _Buffer.Length) Then Exit While
End While
Else
_ResponseData = "FTP data socket failed to connect."
' Throw New MPException(AppSettings.Item("Project"),
"MP.IT.Web.Library.FTP - GetFileList subroutine failed - FTP data
socket failed to connect.", "")
End If

Dim _Parts() As String = _Data.Split(_EndLine)

' Close and destroy the FTP data socket.
If (_FTPDataSocket Is Nothing = False) Then
_FTPDataSocket.Close()
_FTPDataSocket = Nothing
End If

Return _Parts

End Function

'''<summary>
''' Public Function: GetFileSize - This function will get the size
of a provided file name.
'''</summary>
'''<param name="fileName">As String</param>
'''<returns>Function returns a Long.</returns>
' Get the size of the file on the FTP server.
Public Function GetFileSize(ByVal fileName As String) As Long

' Check to see if user is logged into FTP host.
If Not _FTPLogin Then
Login()
End If

Dim _FileSize As Long

'Send an FTP SIZE command.
SendCommand("SIZE ", fileName)
_FileSize = 0

Return _FileSize = Int64.Parse(_ResponseData.Substring(4))

End Function

'''<summary>
''' Public Sub: DownloadFile - This subroutine gets a specific
file.
'''<param name="fileName">As String</param>
'''<param name="filePath">As String</param>
'''<optional param name="fileResume">As Boolean</param>
'''<returns>Subroutine returns nothing.</returns>
Public Sub DownloadFile(ByVal fileName As String, ByVal filePath As
String, Optional ByVal fileResume As Boolean = False)

' Check to see if user is logged into FTP host.
If Not _FTPLogin Then
Login()
End If

' Set the FTP mode to binary.
SetBinaryMode(True)

' Create an FTP data socket.
Dim _FTPDataSocket As Socket = CreateDataSocket()

' Create a file.
Dim _FileStream As Stream
If (Not (File.Exists(filePath & fileName))) Then
_FileStream = File.Create(filePath & fileName)
_FileStream.Close()
End If

Dim _FTPFileStreamOutput As FileStream
_FTPFileStreamOutput = New FileStream(filePath & fileName,
FileMode.Open)

If fileResume Then
Dim _FileOffset As Long
_FileOffset = _FTPFileStreamOutput.Length

If (_FileOffset > 0) Then
' Send an FTP REST command to restart a file.
SendCommand("REST ", _FileOffset)
If (_ResponseCode <> 350) Then
'The FTP host does not support resuming.
_FileOffset = 0
End If
End If
If (_FileOffset <> 0) Then
_FTPFileStreamOutput.Seek(_FileOffset,
SeekOrigin.Begin)
End If
End If

'Send an FTP RETR command to retrieve a file.
SendCommand("RETR ", fileName)

Const _EndLine As Char = "\n"
Const _BufferSize As Integer = 512

Dim _Data As String = ""
Dim _Buffer(_BufferSize) As Byte
Dim _BytesRead As Integer = 0

If _FTPDataSocket.Connected Then
While (True)
Array.Clear(_Buffer, 0, _BufferSize)
_BytesRead = _FTPDataSocket.Receive(_Buffer,
_Buffer.Length, 0)
_FTPFileStreamOutput.Write(_Buffer, 0, _BytesRead)

If (_BytesRead < _Buffer.Length) Then Exit While
End While
Else
_ResponseData = "FTP data socket failed to connect."
' Throw New MPException(AppSettings.Item("Project"),
"MP.IT.Web.Library.FTP - GetFile subroutine failed - FTP data socket
failed to connect.", "")
End If

_FTPFileStreamOutput.Close()

' Close and destroy the FTP data socket.
If (_FTPDataSocket Is Nothing = False) Then
_FTPDataSocket.Close()
_FTPDataSocket = Nothing
End If

End Sub

'''<summary>
''' Public Sub: UploadFile - This subroutine uploads a specific
file to an FTP host.
'''<param name="fileName">As String</param>
'''<param name="filePath">As String</param>
'''<optional param name="fileResume">As Boolean</param>
'''<returns>Subroutine returns nothing.</returns>
Public Sub UploadFile(ByVal fileName As String, ByVal filePath As
String, Optional ByVal fileResume As Boolean = False)

' Check to see if user is logged into FTP host.
If Not _FTPLogin Then
Login()
End If

' Set the FTP mode to binary.
SetBinaryMode(True)

' Create an FTP data socket.
Dim _FTPDataSocket As Socket = CreateDataSocket()

' Check to see if the file exists locally before the upload.
If (File.Exists(filePath & fileName)) Then

' Open the input stream to read the source file.
Dim _FTPFileStreamInput As FileStream
_FTPFileStreamInput = New FileStream(filePath & fileName,
FileMode.Open)

If fileResume Then
' Check to see if part of the file has already been
uploaded.
Dim _FileOffset As Long
_FileOffset = 0

Try
_FileOffset = GetFileSize(fileName)
Catch ex As Exception
_FileOffset = 0
End Try

If (_FileOffset > 0) Then
' Send an FTP REST command to restart a file.
SendCommand("REST ", _FileOffset)
If (_ResponseCode <> 350) Then
'The FTP host does not support resuming.
_FileOffset = 0
End If
End If

If (_FileOffset <> 0) Then
_FTPFileStreamInput.Seek(_FileOffset,
SeekOrigin.Begin)
End If
End If

' Send an FTP STOR command to store a file.
SendCommand("STOR ", fileName)

' Upload the file.
Const _BufferSize As Integer = 512
Dim _Buffer(_BufferSize) As Byte
Dim _BytesRead As Integer = 0

_BytesRead = _FTPFileStreamInput.Read(_Buffer, 0,
_Buffer.Length)
If _FTPDataSocket.Connected Then
While (_BytesRead > 0)
_FTPDataSocket.Send(_Buffer, _BytesRead, 0)
_BytesRead = _FTPFileStreamInput.Read(_Buffer, 0,
_Buffer.Length)
End While

Else
_ResponseData = "FTP data socket failed to
connect."
' Throw New
MPException(AppSettings.Item("Project"), "MP.IT.Web.Library.FTP -
UploadFile subroutine failed - FTP data socket failed to connect.", "")
End If
_FTPFileStreamInput.Close()

Else
_ResponseData = "File to upload does not exist on local
machine."
' Throw New MPException(AppSettings.Item("Project"),
"MP.IT.Web.Library.FTP - UploadFile subroutine failed - file to upload
does not exist on local machine.", "")
End If

' Close and destroy the FTP data socket.
If (_FTPDataSocket Is Nothing = False) Then
_FTPDataSocket.Close()
_FTPDataSocket = Nothing
End If

End Sub

'''<summary>
''' Public Sub: UploadFile - This subroutine deletes a specific
file on an FTP host.
'''<param name="fileName">As String</param>
'''<returns>Subroutine returns nothing.</returns>
Public Sub DeleteFile(ByVal fileName As String)

' Check to see if user is logged into FTP host.
If Not _FTPLogin Then
Login()
End If

' Send an FTP DELE command to delete a file.
SendCommand("DELE ", fileName)

End Sub

'''<summary>
''' Public Sub: RenameFile - This subroutine renames a specific
file on an FTP host.
'''<param name="fileName">As String</param>
'''<param name="fileNewName">As String</param>
'''<returns>Subroutine returns nothing.</returns>
Public Sub RenameFile(ByVal fileName As String, ByVal fileNewName
As String)

' Check to see if user is logged into FTP host.
If Not _FTPLogin Then
Login()
End If

' Send an FTP RNFR command to select a file to be renamed.
SendCommand("RNFR ", fileName)

'Send an FTP RNTO command to rename the selected file to a new
file name.
SendCommand("RNTO ", fileNewName)

End Sub

'''<summary>
''' Public Sub: GetDirectory - This subroutine gets the current
directory on an FTP host.
'''<returns>Subroutine returns nothing.</returns>
Public Sub GetDirectory()

' Check to see if user is logged into FTP host.
If Not _FTPLogin Then
Login()
End If

'Send an FTP CWD command to change to a directory.
SendCommand("PWD ", "")

End Sub

'''<summary>
''' Public Sub: ChangeDirectory - This subroutine changes to a
directory on an FTP host.
'''<param name="directoryName">As String</param>
'''<returns>Subroutine returns nothing.</returns>
Public Sub ChangeDirectory(ByVal directoryName As String)

' Check to see if user is logged into FTP host.
If Not _FTPLogin Then
Login()
End If

'Check if in the root directory.
If (directoryName.Equals(".")) Then
Exit Sub
End If

'Send an FTP CWD command to change to a directory.
SendCommand("CWD ", directoryName)

End Sub

'''<summary>
''' Public Sub: CreateDirectory - This subroutine creates a new
directory on an FTP host.
'''<param name="directoryName">As String</param>
'''<returns>Subroutine returns nothing.</returns>
Public Sub CreateDirectory(ByVal directoryName As String)

' Check to see if user is logged into FTP host.
If Not _FTPLogin Then
Login()
End If

'Send an FTP MKD command to make a new directory.
SendCommand("MKD ", directoryName)

End Sub

'''<summary>
''' Public Sub: RemoveDirectory - This subroutine removes a
directory on an FTP host.
'''<param name="directoryName">As String</param>
'''<returns>Subroutine returns nothing.</returns>
Public Sub RemoveDirectory(ByVal directoryName As String)

' Check to see if user is logged into FTP host.
If Not _FTPLogin Then
Login()
End If

'Send an FTP RMD command to remove a directory.
SendCommand("RMD ", directoryName)

End Sub

#End Region

#Region "Private Methods"

'''<summary>
''' Private Sub: CreateCommandSocket - Provided a Host and a port
this subroutine will instantiate an FTP command socket.
'''</summary>
'''<returns>Subroutine returns nothing.</returns>
Private Sub CreateCommandSocket()

' Create the FTP command socket.
_FTPCommandSocket = New Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp)

Try
Dim HostMachine As IPEndPoint = New
IPEndPoint(Dns.Resolve(_Host).AddressList(0), _Port)
Try
' Connect the FTP command socket to the FTP host
machine.
_FTPCommandSocket.Connect(HostMachine)
Catch ex As Exception
' Connection could not be opened due to malformed
connection.
_ResponseData = "FTP Command Socket Connection Could
Not Be Established."
' Throw New MPException(AppSettings.Item("Project"),
"MP.IT.Web.Library.FTP - FTP Command Socket Connection Could Not Be
Established.", ex)
End Try
Catch ex As Exception
' Connection could not be opened because DNS cannot resolve
the host IP.
_ResponseData = "FTP Command Socket Connection Could Not Be
Established. Connection could not be opened because DNS cannot resolve
the host IP."
' Throw New MPException(AppSettings.Item("Project"),
"MP.IT.Web.Library.FTP - FTP Command Socket Connection Could Not Be
Established. DNS cannot resolve the FTP host.", ex)
End Try
_ResponseData = "FTP Command Socket Connection Established."
ReadResponse()

End Sub

'''<summary>
''' Private Function: CreateDataSocket - Provided that a PASV
command has been sent to the host, this function returns
''' an FTP data socket.
'''</summary>
'''<returns>Subroutine returns nothing.</returns>
Private Function CreateDataSocket() As Socket

Dim _FTPDataSocket As Socket
Dim _FTPHostIPFrontBracket As Integer
Dim _FTPHostIPBackBracket As Integer
Dim _FTPHostIPData As String
Dim _FTPHostIPLength As Integer
Dim _FTPHostIPPartCount As Integer
Dim _FTPHostIPParts(6) As Integer
Dim _FTPHostIPCharater As Char
Dim _Buffer As String
Dim _Counter As Integer

'Send an FTP PASV command to use passive data connection.
SendCommand("PASV", "")

_FTPHostIPFrontBracket = _ResponseData.IndexOf("(")
_FTPHostIPBackBracket = _ResponseData.IndexOf(")")
_FTPHostIPData = _ResponseData.Substring(_FTPHostIPFrontBracket
+ 1, _FTPHostIPBackBracket - _FTPHostIPFrontBracket - 1)

_FTPHostIPLength = _FTPHostIPData.Length
_FTPHostIPPartCount = 0
_Buffer = ""

For _Counter = 0 To ((_FTPHostIPLength - 1) And
_FTPHostIPPartCount <= 6)
_FTPHostIPCharater =
Char.Parse(_FTPHostIPData.Substring(_Counter, 1))
If (Char.IsDigit(_FTPHostIPCharater)) Then
_Buffer += _FTPHostIPCharater
ElseIf (_FTPHostIPCharater <> ",") Then
' Throw New MPException(AppSettings.Item("Project"),
"MP.IT.Web.Library.FTP - FTP Host did not accept the PASV command.",
"")
End If

If ((_FTPHostIPCharater = ",") Or (_Counter + 1 =
_FTPHostIPLength)) Then
Try
_FTPHostIPParts(_FTPHostIPPartCount) =
Int32.Parse(_Buffer)
_FTPHostIPPartCount += 1
_Buffer = ""
Catch ex As Exception
' Throw New
MPException(AppSettings.Item("Project"), "MP.IT.Web.Library.FTP - FTP
Host did not accept the PASV command.", ex)
End Try
End If
Next

' Create the data host.
Dim _DataHost As String = _FTPHostIPParts(0) & "." &
_FTPHostIPParts(1) & "." & _FTPHostIPParts(2) & "." &
_FTPHostIPParts(3)

' Create the data port.
Dim _DataPort As Integer = _FTPHostIPParts(4) << 8

' Determine the data port number.
_DataPort = _DataPort + _FTPHostIPParts(5)

' Create the FTP data socket from the data host and data port.
_FTPDataSocket = New Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp)

Try
Dim HostMachine As IPEndPoint = New
IPEndPoint(Dns.Resolve(_DataHost).AddressList(0), _DataPort)
Try
' Connect the FTP data socket to the FTP host machine.
_FTPDataSocket.Connect(HostMachine)
Return _FTPDataSocket
Catch ex As Exception
' Connection could not be opened due to malformed
connection.
_ResponseData = "FTP Data Socket Connection Could Not
Be Established."
' Throw New MPException(AppSettings.Item("Project"),
"MP.IT.Web.Library.FTP - FTP Data Socket Connection Could Not Be
Established.", ex)
End Try
Catch ex As Exception
' Connection could not be opened because DNS cannot resolve
the host IP.
_ResponseData = "FTP Data Socket Connection Could Not Be
Established. Connection could not be opened because DNS cannot resolve
the host IP."
' Throw New MPException(AppSettings.Item("Project"),
"MP.IT.Web.Library.FTP - FTP Data Socket Connection Could Not Be
Established. DNS cannot resolve the FTP host.", ex)
End Try
_ResponseData = "FTP Data Socket Connection Established."

End Function

'''<summary>
''' Private Sub: ReadResponse - This subroutine will read line by
line the reply to
''' a command sent to an FTP host.
'''</summary>
'''<returns>Function returns a string.</returns>
Private Sub ReadResponse()

' Read the response from the FTP host.
_ResponseData = ReadLine(False)
_ResponseCode = Int32.Parse(_ResponseData.Substring(0, 3))

End Sub

'''<summary>
''' Private Function: ReadLine - This function handles the actual
reading of the FTP host reply.
'''</summary>
'''<param name="clearResponse">As Boolean</param>
'''<returns>Function returns a string.</returns>
Private Function ReadLine(ByVal clearResponse As Boolean) As String

Const _EndLine As Char = "\n"
Const _BufferSize As Integer = 512

Dim _Data As String = ""
Dim _Buffer(_BufferSize) As Byte
Dim _BytesRead As Integer = 0

If (clearResponse = True) Then _ResponseData = String.Empty

While (True)
Array.Clear(_Buffer, 0, _BufferSize)
_BytesRead = _FTPCommandSocket.Receive(_Buffer,
_Buffer.Length, 0)
_Data += ASCII.GetString(_Buffer, 0, _BytesRead)

If (_BytesRead < _Buffer.Length) Then Exit While
End While

Dim _Parts() As String = _Data.Split(_EndLine)

If (_Parts.Length > 2) Then
_ResponseData = _Parts(_Parts.Length - 2)
Else
_ResponseData = _Parts(0)
End If

If (_ResponseData.Substring(3, 1).Equals(" ") = False) Then
Return ReadLine(False)
End If

Return _ResponseData
End Function

#End Region

End Class
 
T

Tom Shelton

All,

I am currently developing an FTP class in VB.NET. It's kid tested,
mother approved when trying to access an FTP Server on a Windows box
meaning I can connect, run commands, upload and download a file no
problem. My issues come when I try to use the same class with the same
commands to access an FTP server on a UNIX box. I can connect and login
just fine, but after that all my commands come back "500 'PWD': command
not understood.". Has anyone experienced this error and can help me
solve it. In order to help everyone out the following is my class:

<snip>

Craig...

Is there a reason you are implementing this code when there are free
and working ftp clients available for .NET (Indy project comes to
mind)? If this is for personal learning I will be glad to look over
this code, but it might take a little debugging time :)
 
C

craig.overton

Tom,

You hit the nail on the head, I am learning, but I just can't seem to
understand how it works so well with a Windows environment FTP server
and then won't get passed the password command in the UNIX environment
FTP. Take as much time as you want. I am interested to know and the
code should be cut and paste for you.

Craig
 
T

Tom Shelton

Tom,

You hit the nail on the head, I am learning, but I just can't seem to
understand how it works so well with a Windows environment FTP server
and then won't get passed the password command in the UNIX environment
FTP. Take as much time as you want. I am interested to know and the
code should be cut and paste for you.

Craig

Well... Actually, it's a bit hard to cut and past through Google.
But, I've almost got it to compile :)

My first response - since I haven't got it to compile just yet is, you
obviously didn't have Option Strict turned on. I would suggest that
you make this a habbit for most code. Anyway, I'll get back to you
once I've got a clean compile.
 
C

craig.overton

Tom,

You hit the nail on the head, I am learning, but I just can't seem to
understand how it works so well with a Windows environment FTP server
and then won't get passed the password command in the UNIX environment
FTP. Take as much time as you want. I am interested to know and the
code should be cut and paste for you.

Craig
 
C

craig.overton

Tom,

Don't bother. I found my mistake and I am pretty much an idiot for it.
Basically I have my subroutine for sending commands called SendCommand.
In that sub I take care of adding the space character after the command
before the command arguements. Well I really should have cleaned up
that sub to make it more efficient. Basically not all FTP commands have
arguements so I really shouldn't being adding that space unless there
are arguements. To make matters even more fun, in all my subroutines
thereafter I added a space after the FTP command and then shipped it to
the SendCommand sub which was already messed up, thus actually doubling
the space character between the FTP command and the FTP command
arguements if there were arguements. Somehow Windows based FTP servers
let this fly whereas Unix FTP servers cannot even understand what was
sent to it as a command. The fixed code that is working across the
board is below. There isn't much it doesn't do. I should probably add
events and a lot more error checking, but it will do for now: Tom thank
you for at least taking some time to look at it.

Craig

Imports System
Imports System.Net
Imports System.IO
Imports System.Text
Imports System.Text.ASCIIEncoding
Imports System.Net.Sockets
Imports System.Configuration
Imports System.Resources

Public Class FTPClient

#Region "Local Properties"

'''<summary>
''' Public Property: Host - String variable.
'''</summary>
Public Property Host() As String
Get
Return _Host
End Get
Set(ByVal Value As String)
_Host = Value
End Set
End Property

'''<summary>
''' Public Property: Path - String variable.
'''</summary>
Public Property Path() As String
Get
Return _Path
End Get
Set(ByVal Value As String)
_Path = Value
End Set
End Property

'''<summary>
''' Public Property: User - String variable.
'''</summary>
Public Property User() As String
Get
Return _User
End Get
Set(ByVal Value As String)
_User = Value
End Set
End Property

'''<summary>
''' Public Property: Password - String variable.
'''</summary>
Public Property Password() As String
Get
Return _Password
End Get
Set(ByVal Value As String)
_Password = Value
End Set
End Property

'''<summary>
''' Public Property: Port - String variable.
'''</summary>
Public Property Port() As String
Get
Return _Port
End Get
Set(ByVal Value As String)
_Port = Value
End Set
End Property

'''<summary>
''' Public ReadOnly Property: ResponseCode - String variable.
'''</summary>
Public ReadOnly Property ResponseCode() As String
Get
Return _ResponseCode
End Get
End Property

'''<summary>
''' Public ReadOnly Property: ResponseData - String variable.
'''</summary>
Public ReadOnly Property ResponseData() As String
Get
Return _ResponseData
End Get
End Property

#End Region

' FTP Default Properties.
Private _Host As String = "127.0.0.1"
Private _Path As String = "."
Private _User As String = "anonymous"
Private _Password As String = "(e-mail address removed)"
Private _Port As Integer = 21
Private _ResponseCode As Integer
Private _ResponseData As String
Private _FTPCommandSocket As Socket = Nothing
Private _FTPLogin As Boolean = False
Private _FTPCommandSocketInstalled As Boolean = False

#Region "Public Methods"

Public Sub New()

End Sub

'''<summary>
''' Public Function: Login - This function will create a command
and data socket and then send the
''' login credentials to the FTP host.
'''</summary>
'''<returns>Function returns a Boolean.</returns>
Public Function Login() As Boolean

' Create an FTP command socket.
CreateCommandSocket()

' Send the gathered login information to the FTP host.
Try
SendCommand("USER", _User)
SendCommand("PASS", _Password)
_FTPLogin = True
Catch ex As Exception
' Login did not work because the FTP login information was
not accepted.
_ResponseData = "FTP Login function not executed."
' Throw New MPException(AppSettings.Item("Project"),
"MP.IT.Web.Library.FTP - FTP login information was not accepted", ex)
Return False
End Try

' Login successful.
Return True

End Function

'''<summary>
''' Public Sub: Logout - This subroutine will disconnect and close
an FTP command and data socket.
'''</summary>
'''<returns>Subroutine returns nothing.</returns>
Public Sub Logout()

' Close and destroy the FTP command socket.
If (_FTPCommandSocket Is Nothing = False) Then
SendCommand("QUIT", "")
_FTPCommandSocket.Close()
_FTPCommandSocket = Nothing
End If
End Sub

'''<summary>
''' Public Sub: SendCommand - Provided a Command and Arguements,
this subroutine will execute an FTP Command.
''' Commands already taken care of with subroutines below:
''' TYPE: Mode (ASCII or Binary)
''' NLST: List files in directory
''' SIZE: Get file Size
''' RETR: Download a file
''' STOR: Upload a file
''' DELE: Delete a file
''' RNFR: Select a file to be renamed
''' RNTO: Rename a selected file
''' PWD: Get a current directory
''' CWD: Change directory
''' RDM: Remove a directory
'''</summary>
'''<param name="FTPCommand">As String</param>
'''<param name="FTPCommandArguements">As String</param>
'''<returns>Function returns an FTP stream.</returns>
Public Sub SendCommand(ByVal FTPCommand As String, ByVal
FTPCommandArguments As String)

Dim _FTPCommand As String
' Combine FTP command with the FTP command arguements.
If FTPCommandArguments = String.Empty Then
_FTPCommand = FTPCommand
Else
_FTPCommand = FTPCommand & " " & FTPCommandArguments
End If
_FTPCommand += Environment.NewLine

' Convert the FTP command into ASCII text.
Dim commandBytes() As Byte = ASCII.GetBytes(_FTPCommand)

Try
' Execute the FTP command on the FTP host.
_FTPCommandSocket.Send(commandBytes, commandBytes.Length,
0)
ReadResponse()
Catch ex As Exception
' Command was not executed.
_ResponseData = "FTP SendCommand subroutine not executed."
' Throw New MPException(AppSettings.Item("Project"),
"MP.IT.Web.Library.FTP - FTP command was not accepted", ex)
End Try
End Sub

'''<summary>
''' Public Sub: SetBinaryMode - This subroutine sets the FTP mode
to binary.
'''<param name="mode">As Boolean</param>
'''<returns>Subroutine returns nothing.</returns>
Public Sub SetBinaryMode(ByVal mode As Boolean)

If (mode) Then
'Send the FTP TYPE command as binary.
SendCommand("TYPE", "I")
Else
'Send the FTP TYPE command as ASCII.
SendCommand("TYPE", "A")
End If
End Sub

'''<summary>
''' Public Function: GetDirectoryFileList - This function will get
the names of the files from the provided directory name.
'''</summary>
'''<param name="directoryName">As String</param>
'''<returns>Function returns a string.</returns>
Public Function GetFileList(ByVal directoryName As String) As
String()

' Check to see if user is logged into FTP host.
If Not _FTPLogin Then
Login()
End If

' Create an FTP data socket.
Dim _FTPDataSocket As Socket = CreateDataSocket()

'Send an FTP NLST command.
SendCommand("NLST", directoryName)

Const _EndLine As Char = "\n"
Const _BufferSize As Integer = 512

Dim _Data As String = ""
Dim _Buffer(_BufferSize) As Byte
Dim _BytesRead As Integer = 0

If _FTPDataSocket.Connected Then
While (True)
Array.Clear(_Buffer, 0, _BufferSize)
_BytesRead = _FTPDataSocket.Receive(_Buffer,
_Buffer.Length, 0)
_Data += ASCII.GetString(_Buffer, 0, _BytesRead)

If (_BytesRead < _Buffer.Length) Then Exit While
End While
Else
_ResponseData = "FTP data socket failed to connect."
' Throw New MPException(AppSettings.Item("Project"),
"MP.IT.Web.Library.FTP - GetFileList subroutine failed - FTP data
socket failed to connect.", "")
End If

Dim _Parts() As String = _Data.Split(_EndLine)

' Close and destroy the FTP data socket.
If (_FTPDataSocket Is Nothing = False) Then
_FTPDataSocket.Close()
_FTPDataSocket = Nothing
End If

Return _Parts

End Function

'''<summary>
''' Public Function: GetFileSize - This function will get the size
of a provided file name.
'''</summary>
'''<param name="fileName">As String</param>
'''<returns>Function returns a Long.</returns>
' Get the size of the file on the FTP server.
Public Function GetFileSize(ByVal fileName As String) As Long

' Check to see if user is logged into FTP host.
If Not _FTPLogin Then
Login()
End If

Dim _FileSize As Long

'Send an FTP SIZE command.
SendCommand("SIZE", fileName)
_FileSize = 0

Return _FileSize = Int64.Parse(_ResponseData.Substring(4))

End Function

'''<summary>
''' Public Sub: DownloadFile - This subroutine gets a specific
file.
'''<param name="fileName">As String</param>
'''<param name="filePath">As String</param>
'''<optional param name="fileResume">As Boolean</param>
'''<returns>Subroutine returns nothing.</returns>
Public Sub DownloadFile(ByVal fileName As String, ByVal filePath As
String, Optional ByVal fileResume As Boolean = False)

' Check to see if user is logged into FTP host.
If Not _FTPLogin Then
Login()
End If

' Set the FTP mode to binary.
SetBinaryMode(True)

' Create an FTP data socket.
Dim _FTPDataSocket As Socket = CreateDataSocket()

' Create a file.
Dim _FileStream As Stream
If (Not (File.Exists(filePath & fileName))) Then
_FileStream = File.Create(filePath & fileName)
_FileStream.Close()
End If

Dim _FTPFileStreamOutput As FileStream
_FTPFileStreamOutput = New FileStream(filePath & fileName,
FileMode.Open)

If fileResume Then
Dim _FileOffset As Long
_FileOffset = _FTPFileStreamOutput.Length

If (_FileOffset > 0) Then
' Send an FTP REST command to restart a file.
SendCommand("REST", _FileOffset)
If (_ResponseCode <> 350) Then
'The FTP host does not support resuming.
_FileOffset = 0
End If
End If
If (_FileOffset <> 0) Then
_FTPFileStreamOutput.Seek(_FileOffset,
SeekOrigin.Begin)
End If
End If

'Send an FTP RETR command to retrieve a file.
SendCommand("RETR", fileName)

Const _EndLine As Char = "\n"
Const _BufferSize As Integer = 512

Dim _Data As String = ""
Dim _Buffer(_BufferSize) As Byte
Dim _BytesRead As Integer = 0

If _FTPDataSocket.Connected Then
While (True)
Array.Clear(_Buffer, 0, _BufferSize)
_BytesRead = _FTPDataSocket.Receive(_Buffer,
_Buffer.Length, 0)
_FTPFileStreamOutput.Write(_Buffer, 0, _BytesRead)

If (_BytesRead < _Buffer.Length) Then Exit While
End While
Else
_ResponseData = "FTP data socket failed to connect."
' Throw New MPException(AppSettings.Item("Project"),
"MP.IT.Web.Library.FTP - GetFile subroutine failed - FTP data socket
failed to connect.", "")
End If

_FTPFileStreamOutput.Close()

' Close and destroy the FTP data socket.
If (_FTPDataSocket Is Nothing = False) Then
_FTPDataSocket.Close()
_FTPDataSocket = Nothing
End If

End Sub

'''<summary>
''' Public Sub: UploadFile - This subroutine uploads a specific
file to an FTP host.
'''<param name="fileName">As String</param>
'''<param name="filePath">As String</param>
'''<optional param name="fileResume">As Boolean</param>
'''<returns>Subroutine returns nothing.</returns>
Public Sub UploadFile(ByVal fileName As String, ByVal filePath As
String, Optional ByVal fileResume As Boolean = False)

' Check to see if user is logged into FTP host.
If Not _FTPLogin Then
Login()
End If

' Set the FTP mode to binary.
SetBinaryMode(True)

' Create an FTP data socket.
Dim _FTPDataSocket As Socket = CreateDataSocket()

' Check to see if the file exists locally before the upload.
If (File.Exists(filePath & fileName)) Then

' Open the input stream to read the source file.
Dim _FTPFileStreamInput As FileStream
_FTPFileStreamInput = New FileStream(filePath & fileName,
FileMode.Open)

If fileResume Then
' Check to see if part of the file has already been
uploaded.
Dim _FileOffset As Long
_FileOffset = 0

Try
_FileOffset = GetFileSize(fileName)
Catch ex As Exception
_FileOffset = 0
End Try

If (_FileOffset > 0) Then
' Send an FTP REST command to restart a file.
SendCommand("REST", _FileOffset)
If (_ResponseCode <> 350) Then
'The FTP host does not support resuming.
_FileOffset = 0
End If
End If

If (_FileOffset <> 0) Then
_FTPFileStreamInput.Seek(_FileOffset,
SeekOrigin.Begin)
End If
End If

' Send an FTP STOR command to store a file.
SendCommand("STOR", fileName)

' Upload the file.
Const _BufferSize As Integer = 512
Dim _Buffer(_BufferSize) As Byte
Dim _BytesRead As Integer = 0

_BytesRead = _FTPFileStreamInput.Read(_Buffer, 0,
_Buffer.Length)
If _FTPDataSocket.Connected Then
While (_BytesRead > 0)
_FTPDataSocket.Send(_Buffer, _BytesRead, 0)
_BytesRead = _FTPFileStreamInput.Read(_Buffer, 0,
_Buffer.Length)
End While

Else
_ResponseData = "FTP data socket failed to
connect."
' Throw New
MPException(AppSettings.Item("Project"), "MP.IT.Web.Library.FTP -
UploadFile subroutine failed - FTP data socket failed to connect.", "")
End If
_FTPFileStreamInput.Close()

Else
_ResponseData = "File to upload does not exist on local
machine."
' Throw New MPException(AppSettings.Item("Project"),
"MP.IT.Web.Library.FTP - UploadFile subroutine failed - file to upload
does not exist on local machine.", "")
End If

' Close and destroy the FTP data socket.
If (_FTPDataSocket Is Nothing = False) Then
_FTPDataSocket.Close()
_FTPDataSocket = Nothing
End If

End Sub

'''<summary>
''' Public Sub: UploadFile - This subroutine deletes a specific
file on an FTP host.
'''<param name="fileName">As String</param>
'''<returns>Subroutine returns nothing.</returns>
Public Sub DeleteFile(ByVal fileName As String)

' Check to see if user is logged into FTP host.
If Not _FTPLogin Then
Login()
End If

' Send an FTP DELE command to delete a file.
SendCommand("DELE", fileName)

End Sub

'''<summary>
''' Public Sub: RenameFile - This subroutine renames a specific
file on an FTP host.
'''<param name="fileName">As String</param>
'''<param name="fileNewName">As String</param>
'''<returns>Subroutine returns nothing.</returns>
Public Sub RenameFile(ByVal fileName As String, ByVal fileNewName
As String)

' Check to see if user is logged into FTP host.
If Not _FTPLogin Then
Login()
End If

' Send an FTP RNFR command to select a file to be renamed.
SendCommand("RNFR", fileName)

'Send an FTP RNTO command to rename the selected file to a new
file name.
SendCommand("RNTO", fileNewName)

End Sub

'''<summary>
''' Public Sub: GetDirectory - This subroutine gets the current
directory on an FTP host.
'''<returns>Subroutine returns nothing.</returns>
Public Sub GetDirectory()

' Check to see if user is logged into FTP host.
If Not _FTPLogin Then
Login()
End If

'Send an FTP CWD command to change to a directory.
SendCommand("PWD", "")

End Sub

'''<summary>
''' Public Sub: ChangeDirectory - This subroutine changes to a
directory on an FTP host.
'''<param name="directoryName">As String</param>
'''<returns>Subroutine returns nothing.</returns>
Public Sub ChangeDirectory(ByVal directoryName As String)

' Check to see if user is logged into FTP host.
If Not _FTPLogin Then
Login()
End If

'Check if in the root directory.
If (directoryName.Equals(".")) Then
Exit Sub
End If

'Send an FTP CWD command to change to a directory.
SendCommand("CWD", directoryName)

End Sub

'''<summary>
''' Public Sub: CreateDirectory - This subroutine creates a new
directory on an FTP host.
'''<param name="directoryName">As String</param>
'''<returns>Subroutine returns nothing.</returns>
Public Sub CreateDirectory(ByVal directoryName As String)

' Check to see if user is logged into FTP host.
If Not _FTPLogin Then
Login()
End If

'Send an FTP MKD command to make a new directory.
SendCommand("MKD", directoryName)

End Sub

'''<summary>
''' Public Sub: RemoveDirectory - This subroutine removes a
directory on an FTP host.
'''<param name="directoryName">As String</param>
'''<returns>Subroutine returns nothing.</returns>
Public Sub RemoveDirectory(ByVal directoryName As String)

' Check to see if user is logged into FTP host.
If Not _FTPLogin Then
Login()
End If

'Send an FTP RMD command to remove a directory.
SendCommand("RMD", directoryName)

End Sub

#End Region

#Region "Private Methods"

'''<summary>
''' Private Sub: CreateCommandSocket - Provided a Host and a port
this subroutine will instantiate an FTP command socket.
'''</summary>
'''<returns>Subroutine returns nothing.</returns>
Private Sub CreateCommandSocket()

' Create the FTP command socket.
_FTPCommandSocket = New Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp)

Try
Dim HostMachine As IPEndPoint = New
IPEndPoint(Dns.Resolve(_Host).AddressList(0), _Port)
Try
' Connect the FTP command socket to the FTP host
machine.
_FTPCommandSocket.Connect(HostMachine)
Catch ex As Exception
' Connection could not be opened due to malformed
connection.
_ResponseData = "FTP Command Socket Connection Could
Not Be Established."
' Throw New MPException(AppSettings.Item("Project"),
"MP.IT.Web.Library.FTP - FTP Command Socket Connection Could Not Be
Established.", ex)
End Try
Catch ex As Exception
' Connection could not be opened because DNS cannot resolve
the host IP.
_ResponseData = "FTP Command Socket Connection Could Not Be
Established. Connection could not be opened because DNS cannot resolve
the host IP."
' Throw New MPException(AppSettings.Item("Project"),
"MP.IT.Web.Library.FTP - FTP Command Socket Connection Could Not Be
Established. DNS cannot resolve the FTP host.", ex)
End Try
_ResponseData = "FTP Command Socket Connection Established."
ReadResponse()

End Sub

'''<summary>
''' Private Function: CreateDataSocket - Provided that a PASV
command has been sent to the host, this function returns
''' an FTP data socket.
'''</summary>
'''<returns>Subroutine returns nothing.</returns>
Private Function CreateDataSocket() As Socket

Dim _FTPDataSocket As Socket
Dim _FTPHostIPFrontBracket As Integer
Dim _FTPHostIPBackBracket As Integer
Dim _FTPHostIPData As String
Dim _FTPHostIPLength As Integer
Dim _FTPHostIPPartCount As Integer
Dim _FTPHostIPParts(6) As Integer
Dim _FTPHostIPCharater As Char
Dim _Buffer As String
Dim _Counter As Integer

'Send an FTP PASV command to use passive data connection.
SendCommand("PASV", "")

_FTPHostIPFrontBracket = _ResponseData.IndexOf("(")
_FTPHostIPBackBracket = _ResponseData.IndexOf(")")
_FTPHostIPData = _ResponseData.Substring(_FTPHostIPFrontBracket
+ 1, _FTPHostIPBackBracket - _FTPHostIPFrontBracket - 1)

_FTPHostIPLength = _FTPHostIPData.Length
_FTPHostIPPartCount = 0
_Buffer = ""

For _Counter = 0 To ((_FTPHostIPLength - 1) And
_FTPHostIPPartCount <= 6)
_FTPHostIPCharater =
Char.Parse(_FTPHostIPData.Substring(_Counter, 1))
If (Char.IsDigit(_FTPHostIPCharater)) Then
_Buffer += _FTPHostIPCharater
ElseIf (_FTPHostIPCharater <> ",") Then
' Throw New MPException(AppSettings.Item("Project"),
"MP.IT.Web.Library.FTP - FTP Host did not accept the PASV command.",
"")
End If

If ((_FTPHostIPCharater = ",") Or (_Counter + 1 =
_FTPHostIPLength)) Then
Try
_FTPHostIPParts(_FTPHostIPPartCount) =
Int32.Parse(_Buffer)
_FTPHostIPPartCount += 1
_Buffer = ""
Catch ex As Exception
' Throw New
MPException(AppSettings.Item("Project"), "MP.IT.Web.Library.FTP - FTP
Host did not accept the PASV command.", ex)
End Try
End If
Next

' Create the data host.
Dim _DataHost As String = _FTPHostIPParts(0) & "." &
_FTPHostIPParts(1) & "." & _FTPHostIPParts(2) & "." &
_FTPHostIPParts(3)

' Create the data port.
Dim _DataPort As Integer = _FTPHostIPParts(4) << 8

' Determine the data port number.
_DataPort = _DataPort + _FTPHostIPParts(5)

' Create the FTP data socket from the data host and data port.
_FTPDataSocket = New Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp)

Try
Dim HostMachine As IPEndPoint = New
IPEndPoint(Dns.Resolve(_DataHost).AddressList(0), _DataPort)
Try
' Connect the FTP data socket to the FTP host machine.
_FTPDataSocket.Connect(HostMachine)
Return _FTPDataSocket
Catch ex As Exception
' Connection could not be opened due to malformed
connection.
_ResponseData = "FTP Data Socket Connection Could Not
Be Established."
' Throw New MPException(AppSettings.Item("Project"),
"MP.IT.Web.Library.FTP - FTP Data Socket Connection Could Not Be
Established.", ex)
End Try
Catch ex As Exception
' Connection could not be opened because DNS cannot resolve
the host IP.
_ResponseData = "FTP Data Socket Connection Could Not Be
Established. Connection could not be opened because DNS cannot resolve
the host IP."
' Throw New MPException(AppSettings.Item("Project"),
"MP.IT.Web.Library.FTP - FTP Data Socket Connection Could Not Be
Established. DNS cannot resolve the FTP host.", ex)
End Try
_ResponseData = "FTP Data Socket Connection Established."

End Function

'''<summary>
''' Private Sub: ReadResponse - This subroutine will read line by
line the reply to
''' a command sent to an FTP host.
'''</summary>
'''<returns>Function returns a string.</returns>
Private Sub ReadResponse()

' Read the response from the FTP host.
_ResponseData = ReadLine(False)
_ResponseCode = Int32.Parse(_ResponseData.Substring(0, 3))

End Sub

'''<summary>
''' Private Function: ReadLine - This function handles the actual
reading of the FTP host reply.
'''</summary>
'''<param name="clearResponse">As Boolean</param>
'''<returns>Function returns a string.</returns>
Private Function ReadLine(ByVal clearResponse As Boolean) As String

Const _EndLine As Char = "\n"
Const _BufferSize As Integer = 512

Dim _Data As String = ""
Dim _Buffer(_BufferSize) As Byte
Dim _BytesRead As Integer = 0

If (clearResponse = True) Then _ResponseData = String.Empty

While (True)
Array.Clear(_Buffer, 0, _BufferSize)
_BytesRead = _FTPCommandSocket.Receive(_Buffer,
_Buffer.Length, 0)
_Data += ASCII.GetString(_Buffer, 0, _BytesRead)

If (_BytesRead < _Buffer.Length) Then Exit While
End While

Dim _Parts() As String = _Data.Split(_EndLine)

If (_Parts.Length > 2) Then
_ResponseData = _Parts(_Parts.Length - 2)
Else
_ResponseData = _Parts(0)
End If

If (_ResponseData.Substring(3, 1).Equals(" ") = False) Then
Return ReadLine(False)
End If

Return _ResponseData
End Function

#End Region

End Class
 
T

Tom Shelton

All,

I am currently developing an FTP class in VB.NET. It's kid tested,
mother approved when trying to access an FTP Server on a Windows box
meaning I can connect, run commands, upload and download a file no
problem. My issues come when I try to use the same class with the same
commands to access an FTP server on a UNIX box. I can connect and login
just fine, but after that all my commands come back "500 'PWD': command
not understood.". Has anyone experienced this error and can help me
solve it. In order to help everyone out the following is my class:

Ok... I won't repost all of the code, but here is the basic problem.
You have extra spaces in the command strings. This happens because you
are passing data like this:

Public Sub GetDirectory()

' Check to see if user is logged into FTP host.
If Not _FTPLogin Then
Login()
End If

'Send an FTP CWD command to change to a directory.
SendCommand("PWD ", "")

End Sub

This should really be:

Public Sub GetDirectory()

' Check to see if user is logged into FTP host.
If Not _FTPLogin Then
Login()
End If

'Send an FTP CWD command to change to a directory.
SendCommand("PWD", "")

End Sub

Of course - this doesn't completely fix your problem. I modified your
SendCommand a little bit as well:

Public Sub SendCommand(ByVal FTPCommand As String, ByVal
FTPCommandArguments As String)

' Combine FTP command with the FTP command arguements.
Dim _FTPCommand As String = IIf(FTPCommandArguments.Length
0, FTPCommand & " " & FTPCommandArguments, FTPCommand)
_FTPCommand += Environment.NewLine

' Convert the FTP command into ASCII text.
Dim commandBytes() As Byte = ASCII.GetBytes(_FTPCommand)

Try
' Execute the FTP command on the FTP host.
_FTPCommandSocket.Send(commandBytes,
commandBytes.Length, 0)
ReadResponse()
Catch ex As Exception
' Command was not executed.
_ResponseData = "FTP SendCommand subroutine not
executed."
' Throw New MPException(AppSettings.Item("Project"),
"MP.IT.Web.Library.FTP - FTP command was not accepted", ex)
End Try
End Sub

I can make a lot more suggestions about how to code this - but this
should fix your immediate issue (go through and fix all the methods to
not pass the command + space, but just the command). Apparently, UNIX
ftp servers - and I could recreate this going to our SCO server - are
picky about the extra spaces, and windows ftp server is not.
 
C

Cor Ligthert [MVP]

Tom,
Is there a reason you are implementing this code when there are free
and working ftp clients available for .NET (Indy project comes to
mind)? If this is for personal learning I will be glad to look over
this code, but it might take a little debugging time :)
At least it is a standard dotNet part now, so there is in my opinion nothing
wrong with learning that.

http://msdn2.microsoft.com/en-us/library/ms144318(VS.80).aspx

Just my thought,

Cor
 
C

craig.overton

Tom,

I figured out my issue 2 seconds before you got your post up. Anyways
everything works great now for Windows and Unix, however now my problem
is timeouts. When I actually went to use it on a Unix server I hit a
snag doing an NLST command as there are some 30,000 files to read thru.
Needless to say my code doesnt make it thru because FTP servers have
timeouts that basically say that if it doesn't get a reply back within
a given time period to close the command connection socket. Now I
tested this theory using two third party apps such as FileZilla and WS
FTP Pro and both of these apps also got timeout errors. So does anyone
know who to change the FTP timeout setting once telnetted into the Unix
box?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top