Microsoft KB Archive/832679: Difference between revisions
m (Text replacement - "<" to "<") |
m (Text replacement - ">" to ">") |
||
Line 249: | Line 249: | ||
ReadReply() | ReadReply() | ||
If (m_iRetValue < | If (m_iRetValue <> 226) Then | ||
MessageString = m_sReply | MessageString = m_sReply | ||
Throw New IOException(m_sReply.Substring(4)) | Throw New IOException(m_sReply.Substring(4)) | ||
Line 296: | Line 296: | ||
ReadReply() | ReadReply() | ||
If (m_iRetValue < | If (m_iRetValue <> 220) Then | ||
CloseConnection() | CloseConnection() | ||
MessageString = m_sReply | MessageString = m_sReply | ||
Line 309: | Line 309: | ||
End If | End If | ||
If (m_iRetValue < | If (m_iRetValue <> 230) Then | ||
'Send an FTP command to send a user logon password to the server. | 'Send an FTP command to send a user logon password to the server. | ||
SendCommand("PASS " & m_sRemotePassword) | SendCommand("PASS " & m_sRemotePassword) | ||
Line 341: | Line 341: | ||
End If | End If | ||
If (m_iRetValue < | If (m_iRetValue <> 200) Then | ||
MessageString = m_sReply | MessageString = m_sReply | ||
Throw New IOException(m_sReply.Substring(4)) | Throw New IOException(m_sReply.Substring(4)) | ||
Line 393: | Line 393: | ||
offset = output.Length | offset = output.Length | ||
If (offset | If (offset > 0) Then | ||
'Send an FTP command to restart. | 'Send an FTP command to restart. | ||
SendCommand("REST " & offset) | SendCommand("REST " & offset) | ||
If (m_iRetValue < | If (m_iRetValue <> 350) Then | ||
offset = 0 | offset = 0 | ||
End If | End If | ||
End If | End If | ||
If (offset | If (offset > 0) Then | ||
npos = output.Seek(offset, SeekOrigin.Begin) | npos = output.Seek(offset, SeekOrigin.Begin) | ||
End If | End If | ||
Line 465: | Line 465: | ||
End If | End If | ||
If (offset | If (offset > 0) Then | ||
SendCommand("REST " & offset) | SendCommand("REST " & offset) | ||
If (m_iRetValue < | If (m_iRetValue <> 350) Then | ||
'The remote server may not support resuming. | 'The remote server may not support resuming. | ||
Line 485: | Line 485: | ||
' Open the input stream to read the source file. | ' Open the input stream to read the source file. | ||
input = New FileStream(sFileName, FileMode.Open) | input = New FileStream(sFileName, FileMode.Open) | ||
If (offset < | If (offset <> 0) Then | ||
input.Seek(offset, SeekOrigin.Begin) | input.Seek(offset, SeekOrigin.Begin) | ||
End If | End If | ||
Line 491: | Line 491: | ||
'Upload the file. | 'Upload the file. | ||
m_iBytes = input.Read(m_aBuffer, 0, m_aBuffer.Length) | m_iBytes = input.Read(m_aBuffer, 0, m_aBuffer.Length) | ||
Do While (m_iBytes | Do While (m_iBytes > 0) | ||
cSocket.Send(m_aBuffer, m_iBytes, 0) | cSocket.Send(m_aBuffer, m_iBytes, 0) | ||
m_iBytes = input.Read(m_aBuffer, 0, m_aBuffer.Length) | m_iBytes = input.Read(m_aBuffer, 0, m_aBuffer.Length) | ||
Line 528: | Line 528: | ||
'Send an FTP command to delete a file. | 'Send an FTP command to delete a file. | ||
SendCommand("DELE " & sFileName) | SendCommand("DELE " & sFileName) | ||
If (m_iRetValue < | If (m_iRetValue <> 250) Then | ||
bResult = False | bResult = False | ||
MessageString = m_sReply | MessageString = m_sReply | ||
Line 547: | Line 547: | ||
'Send an FTP command to rename a file. | 'Send an FTP command to rename a file. | ||
SendCommand("RNFR " & sOldFileName) | SendCommand("RNFR " & sOldFileName) | ||
If (m_iRetValue < | If (m_iRetValue <> 350) Then | ||
MessageString = m_sReply | MessageString = m_sReply | ||
Throw New IOException(m_sReply.Substring(4)) | Throw New IOException(m_sReply.Substring(4)) | ||
Line 555: | Line 555: | ||
'It will overwrite if newFileName exists. | 'It will overwrite if newFileName exists. | ||
SendCommand("RNTO " & sNewFileName) | SendCommand("RNTO " & sNewFileName) | ||
If (m_iRetValue < | If (m_iRetValue <> 250) Then | ||
MessageString = m_sReply | MessageString = m_sReply | ||
Throw New IOException(m_sReply.Substring(4)) | Throw New IOException(m_sReply.Substring(4)) | ||
Line 573: | Line 573: | ||
'Send an FTP command to make a folder on the FTP server. | 'Send an FTP command to make a folder on the FTP server. | ||
SendCommand("MKD " & sDirName) | SendCommand("MKD " & sDirName) | ||
If (m_iRetValue < | If (m_iRetValue <> 257) Then | ||
bResult = False | bResult = False | ||
MessageString = m_sReply | MessageString = m_sReply | ||
Line 592: | Line 592: | ||
'Send an FTP command to remove a folder on the FTP server. | 'Send an FTP command to remove a folder on the FTP server. | ||
SendCommand("RMD " & sDirName) | SendCommand("RMD " & sDirName) | ||
If (m_iRetValue < | If (m_iRetValue <> 250) Then | ||
bResult = False | bResult = False | ||
MessageString = m_sReply | MessageString = m_sReply | ||
Line 615: | Line 615: | ||
'Send an FTP command to change the folder on the FTP server. | 'Send an FTP command to change the folder on the FTP server. | ||
SendCommand("CWD " & sDirName) | SendCommand("CWD " & sDirName) | ||
If (m_iRetValue < | If (m_iRetValue <> 250) Then | ||
bResult = False | bResult = False | ||
MessageString = m_sReply | MessageString = m_sReply | ||
Line 676: | Line 676: | ||
mess = m_sMes.Split(seperator) | mess = m_sMes.Split(seperator) | ||
If (m_sMes.Length | If (m_sMes.Length > 2) Then | ||
m_sMes = mess(mess.Length - 2) | m_sMes = mess(mess.Length - 2) | ||
Else | Else | ||
Line 706: | Line 706: | ||
'Send an FTP command to use a passive data connection. | 'Send an FTP command to use a passive data connection. | ||
SendCommand("PASV") | SendCommand("PASV") | ||
If (m_iRetValue < | If (m_iRetValue <> 227) Then | ||
MessageString = m_sReply | MessageString = m_sReply | ||
Throw New IOException(m_sReply.Substring(4)) | Throw New IOException(m_sReply.Substring(4)) | ||
Line 723: | Line 723: | ||
If (Char.IsDigit(ch)) Then | If (Char.IsDigit(ch)) Then | ||
buf += ch | buf += ch | ||
ElseIf (ch < | ElseIf (ch <> ",") Then | ||
MessageString = m_sReply | MessageString = m_sReply | ||
Throw New IOException("Malformed PASV reply: " & m_sReply) | Throw New IOException("Malformed PASV reply: " & m_sReply) | ||
Line 1,305: | Line 1,305: | ||
ReadReply() | ReadReply() | ||
If (m_iRetValue < | If (m_iRetValue <> 226) Then | ||
MessageString = m_sReply | MessageString = m_sReply | ||
Throw New IOException(m_sReply.Substring(4)) | Throw New IOException(m_sReply.Substring(4)) | ||
Line 1,352: | Line 1,352: | ||
ReadReply() | ReadReply() | ||
If (m_iRetValue < | If (m_iRetValue <> 220) Then | ||
CloseConnection() | CloseConnection() | ||
MessageString = m_sReply | MessageString = m_sReply | ||
Line 1,365: | Line 1,365: | ||
End If | End If | ||
If (m_iRetValue < | If (m_iRetValue <> 230) Then | ||
'Send an FTP command to send a user logon password to the server. | 'Send an FTP command to send a user logon password to the server. | ||
SendCommand("PASS " & m_sRemotePassword) | SendCommand("PASS " & m_sRemotePassword) | ||
Line 1,397: | Line 1,397: | ||
End If | End If | ||
If (m_iRetValue < | If (m_iRetValue <> 200) Then | ||
MessageString = m_sReply | MessageString = m_sReply | ||
Throw New IOException(m_sReply.Substring(4)) | Throw New IOException(m_sReply.Substring(4)) | ||
Line 1,449: | Line 1,449: | ||
offset = output.Length | offset = output.Length | ||
If (offset | If (offset > 0) Then | ||
'Send an FTP command to restart. | 'Send an FTP command to restart. | ||
SendCommand("REST " & offset) | SendCommand("REST " & offset) | ||
If (m_iRetValue < | If (m_iRetValue <> 350) Then | ||
offset = 0 | offset = 0 | ||
End If | End If | ||
End If | End If | ||
If (offset | If (offset > 0) Then | ||
npos = output.Seek(offset, SeekOrigin.Begin) | npos = output.Seek(offset, SeekOrigin.Begin) | ||
End If | End If | ||
Line 1,521: | Line 1,521: | ||
End If | End If | ||
If (offset | If (offset > 0) Then | ||
SendCommand("REST " & offset) | SendCommand("REST " & offset) | ||
If (m_iRetValue < | If (m_iRetValue <> 350) Then | ||
'The remote server may not support resuming. | 'The remote server may not support resuming. | ||
Line 1,541: | Line 1,541: | ||
' Open the input stream to read the source file. | ' Open the input stream to read the source file. | ||
input = New FileStream(sFileName, FileMode.Open) | input = New FileStream(sFileName, FileMode.Open) | ||
If (offset < | If (offset <> 0) Then | ||
input.Seek(offset, SeekOrigin.Begin) | input.Seek(offset, SeekOrigin.Begin) | ||
End If | End If | ||
Line 1,547: | Line 1,547: | ||
'Upload the file. | 'Upload the file. | ||
m_iBytes = input.Read(m_aBuffer, 0, m_aBuffer.Length) | m_iBytes = input.Read(m_aBuffer, 0, m_aBuffer.Length) | ||
Do While (m_iBytes | Do While (m_iBytes > 0) | ||
cSocket.Send(m_aBuffer, m_iBytes, 0) | cSocket.Send(m_aBuffer, m_iBytes, 0) | ||
m_iBytes = input.Read(m_aBuffer, 0, m_aBuffer.Length) | m_iBytes = input.Read(m_aBuffer, 0, m_aBuffer.Length) | ||
Line 1,583: | Line 1,583: | ||
'Send an FTP command to delete a file. | 'Send an FTP command to delete a file. | ||
SendCommand("DELE " & sFileName) | SendCommand("DELE " & sFileName) | ||
If (m_iRetValue < | If (m_iRetValue <> 250) Then | ||
bResult = False | bResult = False | ||
MessageString = m_sReply | MessageString = m_sReply | ||
Line 1,602: | Line 1,602: | ||
'Send an FTP command to rename from a file. | 'Send an FTP command to rename from a file. | ||
SendCommand("RNFR " & sOldFileName) | SendCommand("RNFR " & sOldFileName) | ||
If (m_iRetValue < | If (m_iRetValue <> 350) Then | ||
MessageString = m_sReply | MessageString = m_sReply | ||
Throw New IOException(m_sReply.Substring(4)) | Throw New IOException(m_sReply.Substring(4)) | ||
Line 1,610: | Line 1,610: | ||
'It will overwrite if newFileName exists. | 'It will overwrite if newFileName exists. | ||
SendCommand("RNTO " & sNewFileName) | SendCommand("RNTO " & sNewFileName) | ||
If (m_iRetValue < | If (m_iRetValue <> 250) Then | ||
MessageString = m_sReply | MessageString = m_sReply | ||
Throw New IOException(m_sReply.Substring(4)) | Throw New IOException(m_sReply.Substring(4)) | ||
Line 1,628: | Line 1,628: | ||
'Send an FTP command to make directory on the FTP server. | 'Send an FTP command to make directory on the FTP server. | ||
SendCommand("MKD " & sDirName) | SendCommand("MKD " & sDirName) | ||
If (m_iRetValue < | If (m_iRetValue <> 257) Then | ||
bResult = False | bResult = False | ||
MessageString = m_sReply | MessageString = m_sReply | ||
Line 1,647: | Line 1,647: | ||
'Send an FTP command to remove directory on the FTP server. | 'Send an FTP command to remove directory on the FTP server. | ||
SendCommand("RMD " & sDirName) | SendCommand("RMD " & sDirName) | ||
If (m_iRetValue < | If (m_iRetValue <> 250) Then | ||
bResult = False | bResult = False | ||
MessageString = m_sReply | MessageString = m_sReply | ||
Line 1,670: | Line 1,670: | ||
'Send an FTP command to change directory on the FTP server. | 'Send an FTP command to change directory on the FTP server. | ||
SendCommand("CWD " & sDirName) | SendCommand("CWD " & sDirName) | ||
If (m_iRetValue < | If (m_iRetValue <> 250) Then | ||
bResult = False | bResult = False | ||
MessageString = m_sReply | MessageString = m_sReply | ||
Line 1,727: | Line 1,727: | ||
mess = m_sMes.Split(seperator) | mess = m_sMes.Split(seperator) | ||
If (m_sMes.Length | If (m_sMes.Length > 2) Then | ||
m_sMes = mess(mess.Length - 2) | m_sMes = mess(mess.Length - 2) | ||
Else | Else | ||
Line 1,757: | Line 1,757: | ||
'Send an FTP command to use passive data connection. | 'Send an FTP command to use passive data connection. | ||
SendCommand("PASV") | SendCommand("PASV") | ||
If (m_iRetValue < | If (m_iRetValue <> 227) Then | ||
MessageString = m_sReply | MessageString = m_sReply | ||
Throw New IOException(m_sReply.Substring(4)) | Throw New IOException(m_sReply.Substring(4)) | ||
Line 1,774: | Line 1,774: | ||
If (Char.IsDigit(ch)) Then | If (Char.IsDigit(ch)) Then | ||
buf += ch | buf += ch | ||
ElseIf (ch < | ElseIf (ch <> ",") Then | ||
MessageString = m_sReply | MessageString = m_sReply | ||
Throw New IOException("Malformed PASV reply: " & m_sReply) | Throw New IOException("Malformed PASV reply: " & m_sReply) |
Revision as of 10:23, 21 July 2020
Article ID: 832679
Article Last Modified on 2/14/2006
APPLIES TO
- Microsoft Visual Basic 2005 Express Edition
- Microsoft Visual Basic .NET 2003 Standard Edition
- Microsoft Visual Basic .NET 2002 Standard Edition
SUMMARY
This article describes how to perform the File Transfer Protocol (FTP) operation by using Microsoft Visual Basic .NET or Microsoft Visual Basic 2005. The code samples in this article perform the following FTP commands:
- Upload a file to the FTP site
- Download a file from the FTP site
- Create a folder on the FTP site
- Remove a folder from the FTP site
- Change a working folder on the FTP site
- Remove a file from the FTP site
- Rename a file on the FTP site
Requirements
This article assumes that you are familiar with the following topics:
- Programming with Microsoft Visual Basic .NET or Microsoft Visual Basic 2005
- FTP commands
The following list outlines the recommended hardware, software, network infrastructure, and service packs that you need:
- Microsoft Windows 2000, Microsoft Windows XP, or Microsoft Windows Server 2003
- Visual Basic .NET or Visual Basic 2005
Add references, and declare class variables
You can add references and declare class variables to store a remote host name, to store a remote password, and to set the size of the packet that is used to read and to write data to an FTP server.
Review the following code sample. The "Verify the FTP application" section shows you where to put this code sample and how to make this code sample functional. The "Verify the FTP application" section contains the complete code listing for all the code samples in this article.
Imports System Imports System.Net Imports System.IO Imports System.Text Imports System.Net.Sockets Public Class clsFTP #Region "Class Variable Declarations" Private m_sRemoteHost, m_sRemotePath, m_sRemoteUser As String Private m_sRemotePassword, m_sMess As String Private m_iRemotePort, m_iBytes As Int32 Private m_objClientSocket As Socket Private m_iRetValue As Int32 Private m_bLoggedIn As Boolean Private m_sMes, m_sReply As String 'Set the size of the packet that is used to read and to write data to the FTP server 'to the following specified size. Public Const BLOCK_SIZE = 512 Private m_aBuffer(BLOCK_SIZE) As Byte Private ASCII As Encoding = Encoding.ASCII Public flag_bool As Boolean 'General variable declaration Private m_sMessageString As String #End Region
Define class constructors
You must define the main class constructor with default values. You must define the parameterized constructor that accepts values when the constructor is called.
Review the following code sample. The "Verify the FTP application" section shows you where to put this code sample and how to make this code sample functional. The "Verify the FTP application" section contains the complete code listing for all the code samples in this article.
#Region "Class Constructors" ' Main class constructor Public Sub New() m_sRemoteHost = "microsoft" m_sRemotePath = "." m_sRemoteUser = "anonymous" m_sRemotePassword = "" m_sMessageString = "" m_iRemotePort = 21 m_bLoggedIn = False End Sub ' Parameterized constructor Public Sub New(ByVal sRemoteHost As String, _ ByVal sRemotePath As String, _ ByVal sRemoteUser As String, _ ByVal sRemotePassword As String, _ ByVal iRemotePort As Int32) m_sRemoteHost = sRemoteHost m_sRemotePath = sRemotePath m_sRemoteUser = sRemoteUser m_sRemotePassword = sRemotePassword m_sMessageString = "" m_iRemotePort = 21 m_bLoggedIn = False End Sub #End Region
Set public properties
You must Set or Get the remote FTP server, the remote port, the remote path, the remote password, and the remote user.
Review the following code sample. The "Verify the FTP application" section shows you where to put this code sample and how to make this code sample functional. The "Verify the FTP application" section contains the complete code listing for all the code samples in this article.
#Region "Public Properties" 'Set or Get the name of the FTP server that you want to connect. Public Property RemoteHostFTPServer() As String 'Get the name of the FTP server. Get Return m_sRemoteHost End Get 'Set the name of the FTP server. Set(ByVal Value As String) m_sRemoteHost = Value End Set End Property 'Set or Get the FTP Port Number of the FTP server that you want to connect. Public Property RemotePort() As Int32 'Get the FTP Port Number. Get Return m_iRemotePort End Get 'Set the FTP Port Number. Set(ByVal Value As Int32) m_iRemotePort = Value End Set End Property 'Set or Get the remote path of the FTP server that you want to connect. Public Property RemotePath() As String 'Get the remote path. Get Return m_sRemotePath End Get 'Set the remote path. Set(ByVal Value As String) m_sRemotePath = Value End Set End Property 'Set or Get the remote password of the FTP server that you want to connect. Public Property RemotePassword() As String Get Return m_sRemotePassword End Get Set(ByVal Value As String) m_sRemotePassword = Value End Set End Property 'Set or Get the remote user of the FTP server that you want to connect. Public Property RemoteUser() As String Get Return m_sRemoteUser End Get Set(ByVal Value As String) m_sRemoteUser = Value End Set End Property 'Set the class MessageString. Public Property MessageString() As String Get Return m_sMessageString End Get Set(ByVal Value As String) m_sMessageString = Value End Set End Property #End Region
Use the public sub-procedures and the public functions
The public functions and the public procedures give details about file upload, file download, folder creation, folder removal, change folder, file removal, file rename, set remote username, and set remote password.
Review the following code sample. The "Verify the FTP application" section shows you where to put this code sample and how to make this code sample functional. The "Verify the FTP application" section contains the complete code listing for all the code samples in this article.
#Region "Public Subs and Functions" 'Return a list of files in a string() array from the file system. Public Function GetFileList(ByVal sMask As String) As String() Dim cSocket As Socket Dim bytes As Int32 Dim seperator As Char = ControlChars.Lf Dim mess() As String m_sMes = "" 'Check if you are logged on to the FTP server. If (Not (m_bLoggedIn)) Then Login() End If cSocket = CreateDataSocket() 'Send an FTP command, SendCommand("NLST " & sMask) If (Not (m_iRetValue = 150 Or m_iRetValue = 125)) Then output.Close() MessageString = m_sReply Throw New IOException(m_sReply.Substring(4)) End If m_sMes = "" Do While (True) m_aBuffer.Clear(m_aBuffer, 0, m_aBuffer.Length) bytes = cSocket.Receive(m_aBuffer, m_aBuffer.Length, 0) m_sMes += ASCII.GetString(m_aBuffer, 0, bytes) If (bytes < m_aBuffer.Length) Then Exit Do End If Loop mess = m_sMes.Split(seperator) cSocket.Close() ReadReply() If (m_iRetValue <> 226) Then MessageString = m_sReply Throw New IOException(m_sReply.Substring(4)) End If Return mess End Function ' Get the size of the file on the FTP server. Public Function GetFileSize(ByVal sFileName As String) As Long Dim size As Long If (Not (m_bLoggedIn)) Then Login() End If 'Send an FTP command. SendCommand("SIZE " & sFileName) size = 0 If (m_iRetValue = 213) Then size = Int64.Parse(m_sReply.Substring(4)) Else MessageString = m_sReply Throw New IOException(m_sReply.Substring(4)) End If Return size End Function 'Log on to the FTP server. Public Function Login() As Boolean m_objClientSocket = _ New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp) Dim ep As New IPEndPoint(Dns.Resolve(m_sRemoteHost).AddressList(0), m_iRemotePort) Try m_objClientSocket.Connect(ep) Catch ex As Exception MessageString = m_sReply Throw New IOException("Cannot connect to remote server") End Try ReadReply() If (m_iRetValue <> 220) Then CloseConnection() MessageString = m_sReply Throw New IOException(m_sReply.Substring(4)) End If 'Send an FTP command to send a user logon ID to the server. SendCommand("USER " & m_sRemoteUser) If (Not (m_iRetValue = 331 Or m_iRetValue = 230)) Then Cleanup() MessageString = m_sReply Throw New IOException(m_sReply.Substring(4)) End If If (m_iRetValue <> 230) Then 'Send an FTP command to send a user logon password to the server. SendCommand("PASS " & m_sRemotePassword) If (Not (m_iRetValue = 230 Or m_iRetValue = 202)) Then Cleanup() MessageString = m_sReply Throw New IOException(m_sReply.Substring(4)) End If End If m_bLoggedIn = True 'Call the ChangeDirectory user-defined function to change the folder to the 'remote FTP folder that is mapped. ChangeDirectory(m_sRemotePath) 'Return the final result. Return m_bLoggedIn End Function 'If the value of mode is true, set the binary mode for downloads. Otherwise, set ASCII mode. Public Sub SetBinaryMode(ByVal bMode As Boolean) If (bMode) Then 'Send the FTP command to set the binary mode. '(TYPE is an FTP command that is used to specify representation type.) SendCommand("TYPE I") Else 'Send the FTP command to set ASCII mode. '(TYPE is a FTP command that is used to specify representation type.) SendCommand("TYPE A") End If If (m_iRetValue <> 200) Then MessageString = m_sReply Throw New IOException(m_sReply.Substring(4)) End If End Sub ' Download a file to the local folder of the assembly, and keep the same file name. Public Sub DownloadFile(ByVal sFileName As String) DownloadFile(sFileName, "", False) End Sub ' Download a remote file to the local folder of the assembly, and keep the same file name. Public Sub DownloadFile(ByVal sFileName As String, _ ByVal bResume As Boolean) DownloadFile(sFileName, "", bResume) End Sub 'Download a remote file to a local file name. You must include a path. 'The local file name will be created or will be overwritten, but the path must exist. Public Sub DownloadFile(ByVal sFileName As String, _ ByVal sLocalFileName As String) DownloadFile(sFileName, sLocalFileName, False) End Sub ' Download a remote file to a local file name and include a path. Then, set the ' resume flag. The local file name will be created or will be overwritten, but the path must exist. Public Sub DownloadFile(ByVal sFileName As String, _ ByVal sLocalFileName As String, _ ByVal bResume As Boolean) Dim st As Stream Dim output As FileStream Dim cSocket As Socket Dim offset, npos As Long If (Not (m_bLoggedIn)) Then Login() End If SetBinaryMode(True) If (sLocalFileName.Equals("")) Then sLocalFileName = sFileName End If If (Not (File.Exists(sLocalFileName))) Then st = File.Create(sLocalFileName) st.Close() End If output = New FileStream(sLocalFileName, FileMode.Open) cSocket = CreateDataSocket() offset = 0 If (bResume) Then offset = output.Length If (offset > 0) Then 'Send an FTP command to restart. SendCommand("REST " & offset) If (m_iRetValue <> 350) Then offset = 0 End If End If If (offset > 0) Then npos = output.Seek(offset, SeekOrigin.Begin) End If End If 'Send an FTP command to retrieve a file. SendCommand("RETR " & sFileName) If (Not (m_iRetValue = 150 Or m_iRetValue = 125)) Then output.Close() MessageString = m_sReply Throw New IOException(m_sReply.Substring(4)) End If Do While (True) m_aBuffer.Clear(m_aBuffer, 0, m_aBuffer.Length) m_iBytes = cSocket.Receive(m_aBuffer, m_aBuffer.Length, 0) output.Write(m_aBuffer, 0, m_iBytes) If (m_iBytes <= 0) Then Exit Do End If Loop output.Close() If (cSocket.Connected) Then cSocket.Close() End If ReadReply() If (Not (m_iRetValue = 226 Or m_iRetValue = 250)) Then MessageString = m_sReply Throw New IOException(m_sReply.Substring(4)) End If End Sub ' This is a function that is used to upload a file from your local hard disk to your FTP site. Public Sub UploadFile(ByVal sFileName As String) UploadFile(sFileName, False) End Sub ' This is a function that is used to upload a file from your local hard disk to your FTP site ' and then set the resume flag. Public Sub UploadFile(ByVal sFileName As String, _ ByVal bResume As Boolean) Dim cSocket As Socket Dim offset As Long Dim input As FileStream Dim bFileNotFound As Boolean If (Not (m_bLoggedIn)) Then Login() End If cSocket = CreateDataSocket() offset = 0 If (bResume) Then Try SetBinaryMode(True) offset = GetFileSize(sFileName) Catch ex As Exception offset = 0 End Try End If If (offset > 0) Then SendCommand("REST " & offset) If (m_iRetValue <> 350) Then 'The remote server may not support resuming. offset = 0 End If End If 'Send an FTP command to store a file. SendCommand("STOR " & Path.GetFileName(sFileName)) If (Not (m_iRetValue = 125 Or m_iRetValue = 150)) Then MessageString = m_sReply Throw New IOException(m_sReply.Substring(4)) End If 'Check to see if the file exists before the upload. bFileNotFound = False If (File.Exists(sFileName)) Then ' Open the input stream to read the source file. input = New FileStream(sFileName, FileMode.Open) If (offset <> 0) Then input.Seek(offset, SeekOrigin.Begin) End If 'Upload the file. m_iBytes = input.Read(m_aBuffer, 0, m_aBuffer.Length) Do While (m_iBytes > 0) cSocket.Send(m_aBuffer, m_iBytes, 0) m_iBytes = input.Read(m_aBuffer, 0, m_aBuffer.Length) Loop input.Close() Else bFileNotFound = True End If If (cSocket.Connected) Then cSocket.Close() End If 'Check the return value if the file was not found. If (bFileNotFound) Then MessageString = m_sReply Throw New IOException("The file: " & sFileName & " was not found." & _ " Cannot upload the file to the FTP site.") End If ReadReply() If (Not (m_iRetValue = 226 Or m_iRetValue = 250)) Then MessageString = m_sReply Throw New IOException(m_sReply.Substring(4)) End If End Sub ' Delete a file from the remote FTP server. Public Function DeleteFile(ByVal sFileName As String) As Boolean Dim bResult As Boolean bResult = True If (Not (m_bLoggedIn)) Then Login() End If 'Send an FTP command to delete a file. SendCommand("DELE " & sFileName) If (m_iRetValue <> 250) Then bResult = False MessageString = m_sReply End If ' Return the final result. Return bResult End Function ' Rename a file on the remote FTP server. Public Function RenameFile(ByVal sOldFileName As String, _ ByVal sNewFileName As String) As Boolean Dim bResult As Boolean bResult = True If (Not (m_bLoggedIn)) Then Login() End If 'Send an FTP command to rename a file. SendCommand("RNFR " & sOldFileName) If (m_iRetValue <> 350) Then MessageString = m_sReply Throw New IOException(m_sReply.Substring(4)) End If 'Send an FTP command to rename a file to a file name. 'It will overwrite if newFileName exists. SendCommand("RNTO " & sNewFileName) If (m_iRetValue <> 250) Then MessageString = m_sReply Throw New IOException(m_sReply.Substring(4)) End If ' Return the final result. Return bResult End Function 'This is a function that is used to create a folder on the remote FTP server. Public Function CreateDirectory(ByVal sDirName As String) As Boolean Dim bResult As Boolean bResult = True If (Not (m_bLoggedIn)) Then Login() End If 'Send an FTP command to make a folder on the FTP server. SendCommand("MKD " & sDirName) If (m_iRetValue <> 257) Then bResult = False MessageString = m_sReply End If ' Return the final result. Return bResult End Function ' This is a function that is used to delete a folder on the remote FTP server. Public Function RemoveDirectory(ByVal sDirName As String) As Boolean Dim bResult As Boolean bResult = True 'Check if you are logged on to the FTP server. If (Not (m_bLoggedIn)) Then Login() End If 'Send an FTP command to remove a folder on the FTP server. SendCommand("RMD " & sDirName) If (m_iRetValue <> 250) Then bResult = False MessageString = m_sReply End If ' Return the final result. Return bResult End Function 'This is a function that is used to change the current working folder on the remote FTP server. Public Function ChangeDirectory(ByVal sDirName As String) As Boolean Dim bResult As Boolean bResult = True 'Check if you are in the root directory. If (sDirName.Equals(".")) Then Exit Function End If 'Check if you are logged on to the FTP server. If (Not (m_bLoggedIn)) Then Login() End If 'Send an FTP command to change the folder on the FTP server. SendCommand("CWD " & sDirName) If (m_iRetValue <> 250) Then bResult = False MessageString = m_sReply End If Me.m_sRemotePath = sDirName ' Return the final result. Return bResult End Function ' Close the FTP connection of the remote server. Public Sub CloseConnection() If (Not (m_objClientSocket Is Nothing)) Then 'Send an FTP command to end an FTP server system. SendCommand("QUIT") End If Cleanup() End Sub #End Region
Use the private sub-procedures and the private functions
The following private sub-procedures and private functions are used to read a reply from the FTP server, to send a command to the FTP server that you are connected to, and to create data.
Review the following code sample. The "Verify the FTP application" section shows you where to put this code sample and how to make this code sample functional. The "Verify the FTP application" section contains the complete code listing for all the code samples in this article.
#Region "Private Subs and Functions" ' Read the reply from the FTP server. Private Sub ReadReply() m_sMes = "" m_sReply = ReadLine() m_iRetValue = Int32.Parse(m_sReply.Substring(0, 3)) End Sub ' Clean up some variables. Private Sub Cleanup() If Not (m_objClientSocket Is Nothing) Then m_objClientSocket.Close() m_objClientSocket = Nothing End If m_bLoggedIn = False End Sub ' Read a line from the FTP server. Private Function ReadLine(Optional ByVal bClearMes As Boolean = False) As String Dim seperator As Char = ControlChars.Lf Dim mess() As String If (bClearMes) Then m_sMes = "" End If Do While (True) m_aBuffer.Clear(m_aBuffer, 0, BLOCK_SIZE) m_iBytes = m_objClientSocket.Receive(m_aBuffer, m_aBuffer.Length, 0) m_sMes += ASCII.GetString(m_aBuffer, 0, m_iBytes) If (m_iBytes < m_aBuffer.Length) Then Exit Do End If Loop mess = m_sMes.Split(seperator) If (m_sMes.Length > 2) Then m_sMes = mess(mess.Length - 2) Else m_sMes = mess(0) End If If (Not (m_sMes.Substring(3, 1).Equals(" "))) Then Return ReadLine(True) End If Return m_sMes End Function ' This is a function that is used to send a command to the FTP server that you are connected to. Private Sub SendCommand(ByVal sCommand As String) sCommand = sCommand & ControlChars.CrLf Dim cmdbytes As Byte() = ASCII.GetBytes(sCommand) m_objClientSocket.Send(cmdbytes, cmdbytes.Length, 0) ReadReply() End Sub ' Create a data socket. Private Function CreateDataSocket() As Socket Dim index1, index2, len As Int32 Dim partCount, i, port As Int32 Dim ipData, buf, ipAddress As String Dim parts(6) As Int32 Dim ch As Char Dim s As Socket Dim ep As IPEndPoint 'Send an FTP command to use a passive data connection. SendCommand("PASV") If (m_iRetValue <> 227) Then MessageString = m_sReply Throw New IOException(m_sReply.Substring(4)) End If index1 = m_sReply.IndexOf("(") index2 = m_sReply.IndexOf(")") ipData = m_sReply.Substring(index1 + 1, index2 - index1 - 1) len = ipData.Length partCount = 0 buf = "" For i = 0 To ((len - 1) And partCount <= 6) ch = Char.Parse(ipData.Substring(i, 1)) If (Char.IsDigit(ch)) Then buf += ch ElseIf (ch <> ",") Then MessageString = m_sReply Throw New IOException("Malformed PASV reply: " & m_sReply) End If If ((ch = ",") Or (i + 1 = len)) Then Try parts(partCount) = Int32.Parse(buf) partCount += 1 buf = "" Catch ex As Exception MessageString = m_sReply Throw New IOException("Malformed PASV reply: " & m_sReply) End Try End If Next ipAddress = parts(0) & "." & parts(1) & "." & parts(2) & "." & parts(3) ' Make this call in Visual Basic .NET 2002. You want to ' bitshift the number by 8 bits. Therefore, in Visual Basic .NET 2002, you must ' multiply the number by 2 to the power of 8. 'port = parts(4) * (2 ^ 8) ' Make this call and then comment out the previous line for Visual Basic .NET 2003. port = parts(4) << 8 ' Determine the data port number. port = port + parts(5) s = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp) ep = New IPEndPoint(Dns.Resolve(ipAddress).AddressList(0), port) Try s.Connect(ep) Catch ex As Exception MessageString = m_sReply Throw New IOException("Cannot connect to remote server") 'If you cannot connect to the FTP 'server that is specified, make the boolean variable false. flag_bool = False End Try 'If you can connect to the FTP server that is specified, make the boolean variable true. flag_bool = True Return s End Function #End Region
Connect to the FTP site and then perform operations on the FTP site
You can connect to the FTP server and then perform operations such as create a folder, change the current working folder, upload a file, download a file, and rename a file.
The following information applies to the following code sample.
- The Example1.txt file, the Example2.doc file, and the Example3.doc file are files that exist on your local hard disk. You start your FTP client program from your local hard disk. These files must be put in the C:\
Test
location.Test
is a placeholder for a folder on your local hard disk. - The MyFolder folder and the MyOwnFolder folder are folders that exist on your FTP server.
- The MyOwnFolder folder is a subfolder in the MyFolder folder.
- The MyFolder folder is the folder that your FTP site is mapped to.
- The value of
StrIP
is the Internet Protocol (IP) address of your FTP server.
Review the following code sample. The "Verify the FTP application" section shows you where to put this code sample and how to make this code sample functional. The "Verify the FTP application" section contains the complete code listing for all the code samples in this article.
Sub TestFTP() 'Create an instance of the FTP class that is created. Dim ff As clsFTP Try 'Pass values to the constructor. These values can be overridden by setting 'the appropriate properties on the instance of the clsFTP class. 'The third parameter is the user name. The FTP site is accessed with the user name. 'If there is no specific user name, the user name can be anonymous. 'The fourth parameter is the password. The FTP server is accessed with the password. 'The fifth parameter is the port of the FTP server. The port of the FTP server is typically 21. ff = New clsFTP(StrIP, _ "/Myfolder/", _ "anonymous", _ "", _ 21) 'Try to log on to the FTP server. If (ff.Login() = True) Then 'Change the directory on your FTP site. If (ff.ChangeDirectory("MyOwnFolder") = True) Then 'Successful changing the directory Console.WriteLine("Changed the directory to the directory that was specified" + vbCrLf) Console.WriteLine("Press 'ENTER'") Console.ReadLine() Else 'Unsuccessful changing the directory Console.WriteLine("Unable to change to the directory that was specified" + vbCrLf) Console.WriteLine("Press 'ENTER'") Console.ReadLine() End If 'Create a directory on your FTP site under the previous directory. If (ff.CreateDirectory("FTPFOLDERNEW") = True) Then 'Successful creating the directory Console.WriteLine("A new folder has been created" + vbCrLf) Console.WriteLine("Press 'ENTER'") Console.ReadLine() Else 'Unsuccessful creating the directory Console.WriteLine("A new folder has not been created" + vbCrLf) Console.WriteLine("Press 'ENTER'") Console.ReadLine() End If 'Change the directory on your FTP site under the directory that is specified. If (ff.ChangeDirectory("FTPFOLDERNEW") = True) Then 'Successful changing the directory Console.WriteLine("Changed the directory to the directory that was specified" + vbCrLf) Console.WriteLine("Press 'ENTER'") Console.ReadLine() Else 'Unsuccessful changing the directory Console.WriteLine("Unable to change the directory that was specified" + vbCrLf) Console.WriteLine("Press 'ENTER'") Console.ReadLine() End If ff.SetBinaryMode(True) 'Upload a file from your local hard disk to the FTP site. ff.UploadFile("C:\Test\Example1.txt") ff.UploadFile("C:\Test\Example2.doc") ff.UploadFile("C:\Test\Example3.doc") 'Download a file from the FTP site to your local hard disk. ff.DownloadFile("Example2.doc", "C:\Test\Example2.doc") ' Remove a file from the FTP site. If (ff.DeleteFile("Example1.txt") = True) Then 'Successful removing the file on the FTP site Console.WriteLine("File has been removed from the FTP site" + vbCrLf) Console.WriteLine("Press 'ENTER'") Console.ReadLine() Else 'Unsuccessful removing the file on the FTP site Console.WriteLine("Unable to remove the file on the FTP site" + vbCrLf) Console.WriteLine("Press 'ENTER'") Console.ReadLine() End If 'Rename a file on the FTP site. If (ff.RenameFile("Example3.doc", "Example3_new.doc")) Then 'Successful renaming the file on the FTP site Console.WriteLine("File has been renamed" + vbCrLf) Console.WriteLine("Press 'ENTER'") Console.ReadLine() Else 'Unsuccessful renaming the file on the FTP site Console.WriteLine("File has not been renamed" + vbCrLf) Console.WriteLine("Press 'ENTER'") Console.ReadLine() End If 'Change the directory to one directory before. If (ff.ChangeDirectory("..") = True) Then 'Successful changing the directory Console.WriteLine("Changed the directory to one directory before" + vbCrLf) Console.WriteLine("Press 'ENTER'") Console.ReadLine() Else 'Unsuccessful changing the directory Console.WriteLine("Unable to change the directory" + vbCrLf) Console.WriteLine("Press 'ENTER'") Console.ReadLine() End If End If 'Create a new directory. If (ff.CreateDirectory("MyOwnFolderNew") = True) Then 'Successful creating the directory Console.WriteLine("A new folder has been created" + vbCrLf) Console.WriteLine("Press 'ENTER'") Console.ReadLine() Else 'Unsuccessful creating the directory Console.WriteLine("A new folder has not been created" + vbCrLf) Console.WriteLine("Press 'ENTER'") Console.ReadLine() End If 'Remove the directory that is created on the FTP site. If (ff.RemoveDirectory("MyOwnFolderNew")) Then 'Successful removing the directory on the FTP site Console.WriteLine("Directory has been removed" + vbCrLf) Console.WriteLine("Press 'ENTER'") Console.ReadLine() Else 'Unsuccessful removing the directory on the FTP site Console.WriteLine("Unable to remove the directory" + vbCrLf) Console.WriteLine("Press 'ENTER'") Console.ReadLine() End If Catch ex As System.Exception 'Display the error message. Console.WriteLine("Specific Error=" & ex.Message + vbCrLf) Console.WriteLine("Press 'ENTER' to EXIT") Console.ReadLine() Finally 'Always close the connection to make sure that there are not any not-in-use FTP connections. 'Check if you are logged on to the FTP server and then close the connection. If ff.flag_bool = True Then ff.CloseConnection() End If End Try End Sub
Verify the FTP application
To verify Write permissions to the FTP site and to verify anonymous access to the FTP site, follow these steps:
- Click Start, and then click Run.
- In the Open box, type inetmgr, and then click OK.
- In the Internet Information Services Manager window, expand
MyComputer
.
MyComputer
is the name of your computer.
- In the Internet Information Services Manager window, expand FTP sites.
- Right-click Default FTP Site, and then click Properties.
- In the Default FTP Site Properties dialog box, click to select the Allow anonymous connections check box on the Security Accounts tab.
- In the Default FTP Site Properties dialog box, click to select the Write check box on the Home Directory tab. Click OK to close the Default FTP Site Properties dialog box.
To create a console program, follow these steps:
- Click Start, point to Programs, point to Microsoft Visual Studio .NET, and then click Microsoft Visual Studio .NET.
Note In Visual Studio 2005, click Start, point to Programs, point to Microsoft Visual Studio 2005, and then click Microsoft Visual Studio 2005.
- On the File menu, point to New, and then click Project.
- Under Project Types, click Visual Basic Projects.
Note In Visual Studio 2005, click Visual Basic under Project Types.
- Under Templates, click Console Application.
- In the Name box, type FTP, and then click OK.
By default, the Module1.vb file is created.
- Replace the code in the Module1.vb file with the following code sample:
Imports FTP Module Module1 Sub TestFTP() 'Create an instance of the FTP class that is created. Dim ff As clsFTP Try 'Pass the values to the constructor. These values can be overridden by setting 'the appropriate properties on the instance of the clsFTP class. ff = New clsFTP(StrIP, _ "/MyFolder/", _ "anonymous", _ "", _ 80) 'Try to log on to the FTP server. If (ff.Login() = True) Then 'Change the directory on your FTP site. If (ff.ChangeDirectory("MyOwnFolder") = True) Then 'Successful changing the directory Console.WriteLine("Changed the directory to the directory that was specified" + vbCrLf) Console.WriteLine("Press 'ENTER'") Console.ReadLine() Else 'Unsuccessful changing the directory Console.WriteLine("Unable to change to the directory that was specified" + vbCrLf) Console.WriteLine("Press 'ENTER'") Console.ReadLine() End If 'Create a directory on your FTP site under the previous directory. If (ff.CreateDirectory("FTPFOLDERNEW") = True) Then 'Successful creating the directory Console.WriteLine("A new folder has been created" + vbCrLf) Console.WriteLine("Press 'ENTER'") Console.ReadLine() Else 'Unsuccessful creating the directory Console.WriteLine("A new folder has not been created" + vbCrLf) Console.WriteLine("Press 'ENTER'") Console.ReadLine() End If 'Change the directory on your FTP site under the directory that is specified. If (ff.ChangeDirectory("FTPFOLDERNEW") = True) Then 'Successful changing the directory Console.WriteLine("Changed the directory to the directory that was specified" + vbCrLf) Console.WriteLine("Press 'ENTER'") Console.ReadLine() Else 'Unsuccessful changing the directory Console.WriteLine("Unable to change the directory that was specified" + vbCrLf) Console.WriteLine("Press 'ENTER'") Console.ReadLine() End If ff.SetBinaryMode(True) 'Upload a file from your local hard disk to the FTP site. ff.UploadFile("C:\Test\Example1.txt") ff.UploadFile("C:\Test\Example2.doc") ff.UploadFile("C:\Test\Example3.doc") 'Download a file from the FTP site to your local hard disk. ff.DownloadFile("Example2.doc", "C:\Test\Example4.doc") ' Remove a file from the FTP site. If (ff.DeleteFile("Example1.txt") = True) Then 'Successful removing the file from the FTP site Console.WriteLine("File has been removed from the FTP site" + vbCrLf) Console.WriteLine("Press 'ENTER'") Console.ReadLine() Else 'Unsuccessful removing the file from the FTP site Console.WriteLine("Unable to remove file from the FTP site" + vbCrLf) Console.WriteLine("Press 'ENTER'") Console.ReadLine() End If 'Rename a file on the FTP site. If (ff.RenameFile("Example3.doc", "Example3_new.doc")) Then 'Successful renaming the file on the FTP site Console.WriteLine("File has been renamed" + vbCrLf) Console.WriteLine("Press 'ENTER'") Console.ReadLine() Else 'Unsuccessful renaming the file on the FTP site Console.WriteLine("File has not been renamed" + vbCrLf) Console.WriteLine("Press 'ENTER'") Console.ReadLine() End If 'Change the directory to one directory before. If (ff.ChangeDirectory("..") = True) Then 'Successful changing the directory Console.WriteLine("Changed the directory to one directory before" + vbCrLf) Console.WriteLine("Press 'ENTER'") Console.ReadLine() Else 'Unsuccessful changing the directory Console.WriteLine("Unable to change the directory" + vbCrLf) Console.WriteLine("Press 'ENTER'") Console.ReadLine() End If End If 'Create a new directory. If (ff.CreateDirectory("MyOwnNewFolder") = True) Then 'Successful creating the directory Console.WriteLine("A new folder has been created" + vbCrLf) Console.WriteLine("Press 'ENTER'") Console.ReadLine() Else 'Unsuccessful creating the directory Console.WriteLine("A new folder has not been created" + vbCrLf) Console.WriteLine("Press 'ENTER'") Console.ReadLine() End If 'Remove the directory that was created on the FTP site. If (ff.RemoveDirectory("MyOwnNewFolder")) Then 'Successful removing the directory on the FTP site Console.WriteLine("Directory has been removed" + vbCrLf) Console.WriteLine("Press 'ENTER'") Console.ReadLine() Else 'Unsuccessful removing the directory on the FTP site. Console.WriteLine("Unable to remove the directory" + vbCrLf) Console.WriteLine("Press 'ENTER'") Console.ReadLine() End If Catch ex As System.Exception 'Display the error message. Console.WriteLine("Specific Error= " & ex.Message + vbCrLf) Console.WriteLine("Press 'ENTER' to Exit") Console.ReadLine() Finally 'Always close the connection to make sure that there are not any not-in-use FTP connections. 'Check to see if you are logged on to the FTP server and then close the connection. If ff.flag_bool = True Then ff.CloseConnection() End If End Try End Sub Sub Main() 'Call the procedure from the main. TestFTP() End Sub End Module
To add a Class file to the project, follow these steps:
- In Microsoft Solution Explorer, right-click the FTP project, point to Add, and then click Add New Item.
- Under Templates, click Class.
- In the Name box, type clsFTP.vb, and then click OK.
- Replace the code in the clsFTP.vb file with the following code sample:
' This class permits you to perform direct connections to FTP sites in Visual Basic. NET. ' The class supports the following FTP commands: ' - Upload a file ' - Download a file ' - Create a directory ' - Remove a directory ' - Change directory ' - Remove a file ' - Rename a file ' - Set the user name of the remote user ' - Set the password of the remote user Imports System Imports System.Net Imports System.IO Imports System.Text Imports System.Net.Sockets 'FTP Class Public Class clsFTP #Region "Class Variable Declarations" Private m_sRemoteHost, m_sRemotePath, m_sRemoteUser As String Private m_sRemotePassword, m_sMess As String Private m_iRemotePort, m_iBytes As Int32 Private m_objClientSocket As Socket Private m_iRetValue As Int32 Private m_bLoggedIn As Boolean Private m_sMes, m_sReply As String 'Set the size of the packet that is used to read and to write data to the FTP server 'to the following specified size. Public Const BLOCK_SIZE = 512 Private m_aBuffer(BLOCK_SIZE) As Byte Private ASCII As Encoding = Encoding.ASCII Public flag_bool As Boolean 'General variable declaration Private m_sMessageString As String #End Region #Region "Class Constructors" ' Main class constructor Public Sub New() m_sRemoteHost = "microsoft" m_sRemotePath = "." m_sRemoteUser = "anonymous" m_sRemotePassword = "" m_sMessageString = "" m_iRemotePort = 21 m_bLoggedIn = False End Sub ' Parameterized constructor Public Sub New(ByVal sRemoteHost As String, _ ByVal sRemotePath As String, _ ByVal sRemoteUser As String, _ ByVal sRemotePassword As String, _ ByVal iRemotePort As Int32) m_sRemoteHost = sRemoteHost m_sRemotePath = sRemotePath m_sRemoteUser = sRemoteUser m_sRemotePassword = sRemotePassword m_sMessageString = "" m_iRemotePort = 21 m_bLoggedIn = False End Sub #End Region #Region "Public Properties" 'Set or Get the name of the FTP server that you want to connect to. Public Property RemoteHostFTPServer() As String 'Get the name of the FTP server. Get Return m_sRemoteHost End Get 'Set the name of the FTP server. Set(ByVal Value As String) m_sRemoteHost = Value End Set End Property 'Set or Get the FTP port number of the FTP server that you want to connect to. Public Property RemotePort() As Int32 'Get the FTP port number. Get Return m_iRemotePort End Get 'Set the FTP port number. Set(ByVal Value As Int32) m_iRemotePort = Value End Set End Property 'Set or Get the remote path of the FTP server that you want to connect to. Public Property RemotePath() As String 'Get the remote path. Get Return m_sRemotePath End Get 'Set the remote path. Set(ByVal Value As String) m_sRemotePath = Value End Set End Property 'Set the remote password of the FTP server that you want to connect to. Public Property RemotePassword() As String Get Return m_sRemotePassword End Get Set(ByVal Value As String) m_sRemotePassword = Value End Set End Property 'Set or Get the remote user of the FTP server that you want to connect to. Public Property RemoteUser() As String Get Return m_sRemoteUser End Get Set(ByVal Value As String) m_sRemoteUser = Value End Set End Property 'Set the class messagestring. Public Property MessageString() As String Get Return m_sMessageString End Get Set(ByVal Value As String) m_sMessageString = Value End Set End Property #End Region #Region "Public Subs and Functions" 'Return a list of files from the file system. Return these files in a string() array. Public Function GetFileList(ByVal sMask As String) As String() Dim cSocket As Socket Dim bytes As Int32 Dim seperator As Char = ControlChars.Lf Dim mess() As String m_sMes = "" 'Check to see if you are logged on to the FTP server. If (Not (m_bLoggedIn)) Then Login() End If cSocket = CreateDataSocket() 'Send an FTP command. SendCommand("NLST " & sMask) If (Not (m_iRetValue = 150 Or m_iRetValue = 125)) Then output.Close() MessageString = m_sReply Throw New IOException(m_sReply.Substring(4)) End If m_sMes = "" Do While (True) m_aBuffer.Clear(m_aBuffer, 0, m_aBuffer.Length) bytes = cSocket.Receive(m_aBuffer, m_aBuffer.Length, 0) m_sMes += ASCII.GetString(m_aBuffer, 0, bytes) If (bytes < m_aBuffer.Length) Then Exit Do End If Loop mess = m_sMes.Split(seperator) cSocket.Close() ReadReply() If (m_iRetValue <> 226) Then MessageString = m_sReply Throw New IOException(m_sReply.Substring(4)) End If Return mess End Function ' Get the size of the file on the FTP server. Public Function GetFileSize(ByVal sFileName As String) As Long Dim size As Long If (Not (m_bLoggedIn)) Then Login() End If 'Send an FTP command. SendCommand("SIZE " & sFileName) size = 0 If (m_iRetValue = 213) Then size = Int64.Parse(m_sReply.Substring(4)) Else MessageString = m_sReply Throw New IOException(m_sReply.Substring(4)) End If Return size End Function 'Log on to the FTP server. Public Function Login() As Boolean m_objClientSocket = _ New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp) Dim ep As New IPEndPoint(Dns.Resolve(m_sRemoteHost).AddressList(0), m_iRemotePort) Try m_objClientSocket.Connect(ep) Catch ex As Exception MessageString = m_sReply Throw New IOException("Cannot connect to the remote server") End Try ReadReply() If (m_iRetValue <> 220) Then CloseConnection() MessageString = m_sReply Throw New IOException(m_sReply.Substring(4)) End If 'Send an FTP command to send a user logon ID to the server. SendCommand("USER " & m_sRemoteUser) If (Not (m_iRetValue = 331 Or m_iRetValue = 230)) Then Cleanup() MessageString = m_sReply Throw New IOException(m_sReply.Substring(4)) End If If (m_iRetValue <> 230) Then 'Send an FTP command to send a user logon password to the server. SendCommand("PASS " & m_sRemotePassword) If (Not (m_iRetValue = 230 Or m_iRetValue = 202)) Then Cleanup() MessageString = m_sReply Throw New IOException(m_sReply.Substring(4)) End If End If m_bLoggedIn = True 'Call the ChangeDirectory user-defined function to change the directory to the 'remote FTP folder that is mapped. ChangeDirectory(m_sRemotePath) 'Return the final result. Return m_bLoggedIn End Function 'If the value of mode is true, set binary mode for downloads. Otherwise, set ASCII mode. Public Sub SetBinaryMode(ByVal bMode As Boolean) If (bMode) Then 'Send the FTP command to set the binary mode. '(TYPE is an FTP command that is used to specify representation type.) SendCommand("TYPE I") Else 'Send the FTP command to set ASCII mode. '(TYPE is an FTP command that is used to specify representation type.) SendCommand("TYPE A") End If If (m_iRetValue <> 200) Then MessageString = m_sReply Throw New IOException(m_sReply.Substring(4)) End If End Sub ' Download a file to the local directory of the assembly. Keep the same file name. Public Sub DownloadFile(ByVal sFileName As String) DownloadFile(sFileName, "", False) End Sub ' Download a remote file to the local directory of the Assembly. Keep the same file name. Public Sub DownloadFile(ByVal sFileName As String, _ ByVal bResume As Boolean) DownloadFile(sFileName, "", bResume) End Sub 'Download a remote file to a local file name. You must include a path. 'The local file name will be created or will be overwritten, but the path must exist. Public Sub DownloadFile(ByVal sFileName As String, _ ByVal sLocalFileName As String) DownloadFile(sFileName, sLocalFileName, False) End Sub ' Download a remote file to a local file name. You must include a path. Set the ' resume flag. The local file name will be created or will be overwritten, but the path must exist. Public Sub DownloadFile(ByVal sFileName As String, _ ByVal sLocalFileName As String, _ ByVal bResume As Boolean) Dim st As Stream Dim output As FileStream Dim cSocket As Socket Dim offset, npos As Long If (Not (m_bLoggedIn)) Then Login() End If SetBinaryMode(True) If (sLocalFileName.Equals("")) Then sLocalFileName = sFileName End If If (Not (File.Exists(sLocalFileName))) Then st = File.Create(sLocalFileName) st.Close() End If output = New FileStream(sLocalFileName, FileMode.Open) cSocket = CreateDataSocket() offset = 0 If (bResume) Then offset = output.Length If (offset > 0) Then 'Send an FTP command to restart. SendCommand("REST " & offset) If (m_iRetValue <> 350) Then offset = 0 End If End If If (offset > 0) Then npos = output.Seek(offset, SeekOrigin.Begin) End If End If 'Send an FTP command to retrieve a file. SendCommand("RETR " & sFileName) If (Not (m_iRetValue = 150 Or m_iRetValue = 125)) Then output.Close() MessageString = m_sReply Throw New IOException(m_sReply.Substring(4)) End If Do While (True) m_aBuffer.Clear(m_aBuffer, 0, m_aBuffer.Length) m_iBytes = cSocket.Receive(m_aBuffer, m_aBuffer.Length, 0) output.Write(m_aBuffer, 0, m_iBytes) If (m_iBytes <= 0) Then Exit Do End If Loop output.Close() If (cSocket.Connected) Then cSocket.Close() End If ReadReply() If (Not (m_iRetValue = 226 Or m_iRetValue = 250)) Then MessageString = m_sReply Throw New IOException(m_sReply.Substring(4)) End If End Sub 'This is a function that is used to upload a file from your local hard disk to your FTP site. Public Sub UploadFile(ByVal sFileName As String) UploadFile(sFileName, False) End Sub ' This is a function that is used to upload a file from your local hard disk to your FTP site ' and then set the resume flag. Public Sub UploadFile(ByVal sFileName As String, _ ByVal bResume As Boolean) Dim cSocket As Socket Dim offset As Long Dim input As FileStream Dim bFileNotFound As Boolean If (Not (m_bLoggedIn)) Then Login() End If cSocket = CreateDataSocket() offset = 0 If (bResume) Then Try SetBinaryMode(True) offset = GetFileSize(sFileName) Catch ex As Exception offset = 0 End Try End If If (offset > 0) Then SendCommand("REST " & offset) If (m_iRetValue <> 350) Then 'The remote server may not support resuming. offset = 0 End If End If 'Send an FTP command to store a file. SendCommand("STOR " & Path.GetFileName(sFileName)) If (Not (m_iRetValue = 125 Or m_iRetValue = 150)) Then MessageString = m_sReply Throw New IOException(m_sReply.Substring(4)) End If 'Check to see if the file exists before the upload. bFileNotFound = False If (File.Exists(sFileName)) Then ' Open the input stream to read the source file. input = New FileStream(sFileName, FileMode.Open) If (offset <> 0) Then input.Seek(offset, SeekOrigin.Begin) End If 'Upload the file. m_iBytes = input.Read(m_aBuffer, 0, m_aBuffer.Length) Do While (m_iBytes > 0) cSocket.Send(m_aBuffer, m_iBytes, 0) m_iBytes = input.Read(m_aBuffer, 0, m_aBuffer.Length) Loop input.Close() Else bFileNotFound = True End If If (cSocket.Connected) Then cSocket.Close() End If 'Check the return value if the file was not found. If (bFileNotFound) Then MessageString = m_sReply Throw New IOException("The file: “& sFileName & " was not found. " & _ "Cannot upload the file to the FTP site") End If ReadReply() If (Not (m_iRetValue = 226 Or m_iRetValue = 250)) Then MessageString = m_sReply Throw New IOException(m_sReply.Substring(4)) End If End Sub ' Delete a file from the remote FTP server. Public Function DeleteFile(ByVal sFileName As String) As Boolean Dim bResult As Boolean bResult = True If (Not (m_bLoggedIn)) Then Login() End If 'Send an FTP command to delete a file. SendCommand("DELE " & sFileName) If (m_iRetValue <> 250) Then bResult = False MessageString = m_sReply End If ' Return the final result. Return bResult End Function ' Rename a file on the remote FTP server. Public Function RenameFile(ByVal sOldFileName As String, _ ByVal sNewFileName As String) As Boolean Dim bResult As Boolean bResult = True If (Not (m_bLoggedIn)) Then Login() End If 'Send an FTP command to rename from a file. SendCommand("RNFR " & sOldFileName) If (m_iRetValue <> 350) Then MessageString = m_sReply Throw New IOException(m_sReply.Substring(4)) End If 'Send an FTP command to rename a file to a new file name. 'It will overwrite if newFileName exists. SendCommand("RNTO " & sNewFileName) If (m_iRetValue <> 250) Then MessageString = m_sReply Throw New IOException(m_sReply.Substring(4)) End If ' Return the final result. Return bResult End Function 'This is a function that is used to create a directory on the remote FTP server. Public Function CreateDirectory(ByVal sDirName As String) As Boolean Dim bResult As Boolean bResult = True If (Not (m_bLoggedIn)) Then Login() End If 'Send an FTP command to make directory on the FTP server. SendCommand("MKD " & sDirName) If (m_iRetValue <> 257) Then bResult = False MessageString = m_sReply End If ' Return the final result. Return bResult End Function ' This is a function that is used to delete a directory on the remote FTP server. Public Function RemoveDirectory(ByVal sDirName As String) As Boolean Dim bResult As Boolean bResult = True 'Check if logged on to the FTP server If (Not (m_bLoggedIn)) Then Login() End If 'Send an FTP command to remove directory on the FTP server. SendCommand("RMD " & sDirName) If (m_iRetValue <> 250) Then bResult = False MessageString = m_sReply End If ' Return the final result. Return bResult End Function 'This is a function that is used to change the current working directory on the remote FTP server. Public Function ChangeDirectory(ByVal sDirName As String) As Boolean Dim bResult As Boolean bResult = True 'Check if you are in the root directory. If (sDirName.Equals(".")) Then Exit Function End If 'Check if logged on to the FTP server If (Not (m_bLoggedIn)) Then Login() End If 'Send an FTP command to change directory on the FTP server. SendCommand("CWD " & sDirName) If (m_iRetValue <> 250) Then bResult = False MessageString = m_sReply End If Me.m_sRemotePath = sDirName ' Return the final result. Return bResult End Function ' Close the FTP connection of the remote server. Public Sub CloseConnection() If (Not (m_objClientSocket Is Nothing)) Then 'Send an FTP command to end an FTP server system. SendCommand("QUIT") End If Cleanup() End Sub #End Region #Region "Private Subs and Functions" ' Read the reply from the FTP server. Private Sub ReadReply() m_sMes = "" m_sReply = ReadLine() m_iRetValue = Int32.Parse(m_sReply.Substring(0, 3)) End Sub ' Clean up some variables. Private Sub Cleanup() If Not (m_objClientSocket Is Nothing) Then m_objClientSocket.Close() m_objClientSocket = Nothing End If m_bLoggedIn = False End Sub ' Read a line from the FTP server. Private Function ReadLine(Optional ByVal bClearMes As Boolean = False) As String Dim seperator As Char = ControlChars.Lf Dim mess() As String If (bClearMes) Then m_sMes = "" End If Do While (True) m_aBuffer.Clear(m_aBuffer, 0, BLOCK_SIZE) m_iBytes = m_objClientSocket.Receive(m_aBuffer, m_aBuffer.Length, 0) m_sMes += ASCII.GetString(m_aBuffer, 0, m_iBytes) If (m_iBytes < m_aBuffer.Length) Then Exit Do End If Loop mess = m_sMes.Split(seperator) If (m_sMes.Length > 2) Then m_sMes = mess(mess.Length - 2) Else m_sMes = mess(0) End If If (Not (m_sMes.Substring(3, 1).Equals(" "))) Then Return ReadLine(True) End If Return m_sMes End Function ' This is a function that is used to send a command to the FTP server that you are connected to. Private Sub SendCommand(ByVal sCommand As String) sCommand = sCommand & ControlChars.CrLf Dim cmdbytes As Byte() = ASCII.GetBytes(sCommand) m_objClientSocket.Send(cmdbytes, cmdbytes.Length, 0) ReadReply() End Sub ' Create a data socket. Private Function CreateDataSocket() As Socket Dim index1, index2, len As Int32 Dim partCount, i, port As Int32 Dim ipData, buf, ipAddress As String Dim parts(6) As Int32 Dim ch As Char Dim s As Socket Dim ep As IPEndPoint 'Send an FTP command to use passive data connection. SendCommand("PASV") If (m_iRetValue <> 227) Then MessageString = m_sReply Throw New IOException(m_sReply.Substring(4)) End If index1 = m_sReply.IndexOf("(") index2 = m_sReply.IndexOf(")") ipData = m_sReply.Substring(index1 + 1, index2 - index1 - 1) len = ipData.Length partCount = 0 buf = "" For i = 0 To ((len - 1) And partCount <= 6) ch = Char.Parse(ipData.Substring(i, 1)) If (Char.IsDigit(ch)) Then buf += ch ElseIf (ch <> ",") Then MessageString = m_sReply Throw New IOException("Malformed PASV reply: " & m_sReply) End If If ((ch = ",") Or (i + 1 = len)) Then Try parts(partCount) = Int32.Parse(buf) partCount += 1 buf = "" Catch ex As Exception MessageString = m_sReply Throw New IOException("Malformed PASV reply: " & m_sReply) End Try End If Next ipAddress = parts(0) & "." & parts(1) & "." & parts(2) & "." & parts(3) ' Make this call in Visual Basic .NET 2002. You want to ' bitshift the number by 8 bits. In Visual Basic .NET 2002 you must ' multiply the number by 2 to the power of 8. 'port = parts(4) * (2 ^ 8) ' Make this call and then comment out the previous line for Visual Basic .NET 2003. port = parts(4) << 8 ' Determine the data port number. port = port + parts(5) s = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp) ep = New IPEndPoint(Dns.Resolve(ipAddress).AddressList(0), port) Try s.Connect(ep) Catch ex As Exception MessageString = m_sReply Throw New IOException("Cannot connect to remote server.") 'If you cannot connect to the FTP server that is 'specified, make the boolean variable false. flag_bool = False End Try 'If you can connect to the FTP server that is specified, make the boolean variable true. flag_bool = True Return s End Function #End Region End Class
To change the Startup object of your project, follow these steps:
- On the Project menu, click FTP Properties.
- In the FTP Property Pages dialog box, set the value of the Startup object box to Sub Main, and then click OK.
To build your FTP application, follow these steps:
- On the Build menu, click Build Solution.
- On the Debug menu, click Start to run the application.
Notice on the FTP site that the application creates a directory, uploads a file, downloads a file to your local drive, renames a file, deletes a file, and changes the current directory.
REFERENCES
For additional information, click the following article number to view the article in the Microsoft Knowledge Base:
812404 HOW TO: Write pluggable protocol to support FTP in managed classes by using Visual Basic .NET
For additional information about supported FTP commands, visit the following Microsoft Developer Network (MSDN) Web site:
Keywords: kbvs2005applies kbvs2005swept kbprogramming kbclient kbftp kbhowtomaster KB832679