|
web
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
VB.NET - Issues with VB.NET FTP Class to UNIX FTP ServerI 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 = "anonym***@nowhere.com" 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 craig.over***@gmail.com wrote:
> All, <snip>> > 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: 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 :) -- Tom Shelton [MVP] 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 craig.over***@gmail.com wrote:
> Tom, Well... Actually, it's a bit hard to cut and past through Google.> > 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 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. -- Tom Shelton [MVP] 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 = "anonym***@nowhere.com" 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 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 Tom,
> Is there a reason you are implementing this code when there are free At least it is a standard dotNet part now, so there is in my opinion nothing > 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 :) > wrong with learning that. http://msdn2.microsoft.com/en-us/library/ms144318(VS.80).aspx Just my thought, Cor craig.over***@gmail.com wrote:
> All, Ok... I won't repost all of the code, but here is the basic problem.> > 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: 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. -- Tom Shelton [MVP] Craig,
Did you try use the sample FTP from the 101 2005 samples kit. http://msdn.microsoft.com/vstudio/downloads/101samples/default.aspx Be aware that this are often with a converter from C# converted samples therefore don't use these as samples how to write VBNet programs. But they are nice to learn the classes. I hope this helps, Cor <craig.over***@gmail.com> schreef in bericht Show quoteHide quote news:1143061067.150353.250940@i39g2000cwa.googlegroups.com... > 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 = "anonym***@nowhere.com" > 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 >
what's up? reading xml
Best Practices - Coding Convention Question How do you know when all databindings on form are complete? Reading Excel in VB.NET How to update data in Windows Datagrid DoEvents in VB.NET SQL Distinct Building VB.NET Interface definitions from a COM interface Committing Byte Array to Disk Process BUG? |
|||||||||||||||||||||||