找传奇、传世资源到传世资源站!
VB编程 正文

VB写的FTP客户端程序

  • 资源分类:VB编程
  • 发 布 人:房东的猫
  • 文件大小:115343
  • 文件格式:.rar
  • 浏览次数:47
  • 下载次数: 0
  • 发布时间:9月5日

  • 标签: FTP源码例子
8.5玩家评分(1人评分)
下载后可评
介绍 评论 失效链接反馈

VB写的FTP客户端程序
from clipboard
'********************************************************************************
'CFtpConnection类
'********************************************************************************
'   在该类里面使用了以下几个类和模块
'   CFtpFile    类
'   CFtpFiles   类
'   CTimeout    类
'   MFtpSupport 模块
'
'   同时在该类中使用到了winsock对象,因此在工程的REFERENCES中加入对该对象的引用

'********************************************************************************
'winsock对象的声明
'********************************************************************************
'声明进行控制连接的winsock对象
Private WithEvents wscControl As MSWinsockLib.Winsock
'声明进行数据连接的winsock对象
Private WithEvents wscData As MSWinsockLib.Winsock
'********************************************************************************
'定义类模块的内部属性变量
'********************************************************************************
Private m_strUserName           As String           '定义连接ftp服务器用户名
Private m_strPassword           As String           '定义连接ftp服务器密码
Private m_varFtpServer          As Variant          '定义连接ftp服务器地址
Private m_strCurrentDirectory   As String           '服务器当前工作目录
Private m_bPassiveMode          As Boolean          '定义连接模式
Private m_bBusy                 As Boolean          '定义程序是否正在传输连接
Private m_intTimeout            As Integer          '定义连接超时限制
Private m_TransferMode          As FtpTransferModes '定义传输模式
'********************************************************************************
'公共枚举变量
'********************************************************************************
'连接ftp服务器时的各种状态
Public Enum FTP_CONNECTION_STATES
    FTP_CONNECTION_RESOLVING_HOST
    FTP_CONNECTION_HOST_RESOLVED
    FTP_CONNECTION_CONNECTED
    FTP_CONNECTION_AUTHENTICATION
    FTP_USER_LOGGED
    FTP_ESTABLISHING_DATA_CONNECTION
    FTP_DATA_CONNECTION_ESTABLISHED
    FTP_RETRIEVING_DIRECTORY_INFO
    FTP_DIRECTORY_INFO_COMPLETED
    FTP_TRANSFER_STARTING
    FTP_TRANSFER_COMLETED
End Enum
'ftp服务器各种返回的响应码
Private Enum FTP_RESPONSE_CODES
    FTP_RESPONSE_RESTATRT_MARKER_REPLY = 110
    FTP_RESPONSE_SERVICE_READY_IN_MINUTES = 120
    FTP_RESPONSE_DATA_CONNECTION_ALREADY_OPEN = 125
    FTP_RESPONSE_FILE_STATUS_OK = 150
    FTP_RESPONSE_COMMAND_OK = 200
    FTP_RESPONSE_COMMAND_NOT_IMPLEMENTED_SUPERFLUOUS_AT_THIS_SITE = 202 'superfluous at this site
    FTP_RESPONSE_SYSTEM_STATUS_OR_SYSTEM_HELP_REPLY = 211
    FTP_RESPONSE_DIRECTORY_STATUS = 212
    FTP_RESPONSE_FILE_STATUS = 213
    FTP_RESPONSE_HELP_MESSAGE = 214
    FTP_RESPONSE_NAME_SYSTEM_TYPE = 215
    FTP_RESPONSE_SERVICE_READY_FOR_NEW_USER = 220
    FTP_RESPONSE_SERVICE_CLOSING_CONTROL_CONNECTION = 221
    FTP_RESPONSE_DATA_CONNECTION_OPEN = 225
    FTP_RESPONSE_CLOSING_DATA_CONNECTION = 226
    FTP_RESPONSE_ENTERING_PASSIVE_MODE = 227
    FTP_RESPONSE_USER_LOGGED_IN = 230
    FTP_RESPONSE_REQUESTED_FILE_ACTION_OK_COMPLETED = 250
    FTP_RESPONSE_PATHNAME_CREATED = 257
    FTP_RESPONSE_USER_NAME_OK_NEED_PASSWORD = 331
    FTP_RESPONSE_NEED_ACCOUNT_FOR_LOGIN = 332
    FTP_RESPONSE_REQUESTED_FILE_ACTION_PENDING_FURTHER_INFO = 350
    FTP_RESPONSE_SERVICE_NOT_AVAILABLE_CLOSING_CONTROL_CONNECTION = 421
    FTP_RESPONSE_CANNOT_OPEN_DATA_CONNECTION = 425
    FTP_RESPONSE_CONNECTION_CLOSED_TRANSFER_ABORTED = 426
    FTP_RESPONSE_REQUESTED_FILE_ACTION_NOT_TAKEN = 450
    FTP_RESPONSE_REQUESTED_ACTION_ABORTED = 451
    FTP_RESPONSE_REQUESTED_ACTION_NOT_TAKEN = 452
    FTP_RESPONSE_SYNTAX_ERROR_COMMAND_UNRECOGNIZED = 500
    FTP_RESPONSE_SYNTAX_ERROR_IN_PARAMETERS_OR_ARGUMENTS = 501
    FTP_RESPONSE_COMMAND_NOT_IMPLEMENTED = 502
    FTP_RESPONSE_BAD_SEQUENCE_OF_COMMANDS = 503
    FTP_RESPONSE_COMMAND_NOT_IMPLEMENTED_FOR_THAT_PARAMETER = 504
    FTP_RESPONSE_NOT_LOGGED_IN = 530
    FTP_RESPONSE_NEED_ACCOUNT_FOR_STORING_FILES = 532
    FTP_RESPONSE_REQUESTED_ACTION_NOT_TAKEN_FILE_UNAVAILABLE = 550
    FTP_RESPONSE_REQUESTED_ACTION_ABORTED_PAGE_TYPE_UNKNOWN = 551
    FTP_RESPONSE_REQUESTED_FILE_ACTION_ABORTED_EXCEEDED_STORAGE_ALLOCATION = 552
    FTP_RESPONSE_REQUESTED_ACTION_NOT_TAKEN_FILE_NAME_NOT_ALLOWED = 553
End Enum
'ftp传输模式
Public Enum FtpTransferModes
    FTP_ASCII_MODE 'ASCII模式
    FTP_IMAGE_MODE '二进制模式
End Enum
'********************************************************************************
'类错误
'********************************************************************************
Public Enum FtpErrors
    ERROR_FTP_WINSOCK_AddressInUse
    ERROR_FTP_WINSOCK_AddressNotAvailable
    ERROR_FTP_WINSOCK_AlreadyComplete
    ERROR_FTP_WINSOCK_AlreadyConnected
    ERROR_FTP_WINSOCK_BadState
    ERROR_FTP_WINSOCK_ConnectAborted
    ERROR_FTP_WINSOCK_ConnectionRefused
    ERROR_FTP_WINSOCK_ConnectionReset
    ERROR_FTP_WINSOCK_GetNotSupported
    ERROR_FTP_WINSOCK_HostNotFound
    ERROR_FTP_WINSOCK_HostNotFoundTryAgain
    ERROR_FTP_WINSOCK_InProgress
    ERROR_FTP_WINSOCK_InvalidArg
    ERROR_FTP_WINSOCK_InvalidArgument
    ERROR_FTP_WINSOCK_InvalidOp
    ERROR_FTP_WINSOCK_InvalidPropertyValue
    ERROR_FTP_WINSOCK_MsgTooBig
    ERROR_FTP_WINSOCK_NetReset
    ERROR_FTP_WINSOCK_NetworkSubsystemFailed
    ERROR_FTP_WINSOCK_NetworkUnreachable
    ERROR_FTP_WINSOCK_NoBufferSpace
    ERROR_FTP_WINSOCK_NoData
    ERROR_FTP_WINSOCK_NonRecoverableError
    ERROR_FTP_WINSOCK_NotConnected
    ERROR_FTP_WINSOCK_NotInitialized
    ERROR_FTP_WINSOCK_NotSocket
    ERROR_FTP_WINSOCK_OpCanceled
    ERROR_FTP_WINSOCK_OutOfMemory
    ERROR_FTP_WINSOCK_OutOfRange
    ERROR_FTP_WINSOCK_PortNotSupported
    ERROR_FTP_WINSOCK_SetNotSupported
    ERROR_FTP_WINSOCK_SocketShutdown
    ERROR_FTP_WINSOCK_Success
    ERROR_FTP_WINSOCK_Timedout
    ERROR_FTP_WINSOCK_Unsupported
    ERROR_FTP_WINSOCK_WouldBlock
    ERROR_FTP_WINSOCK_WrongProtocol
    ERROR_FTP_PROTOCOL_SERVICE_READY_IN_MINUTES
    ERROR_FTP_PROTOCOL_USER_NAME_OK_NEED_PASSWORD
    ERROR_FTP_PROTOCOL_NEED_ACCOUNT_FOR_LOGIN
    ERROR_FTP_PROTOCOL_REQUESTED_FILE_ACTION_PENDING_FURTHER_INFO
    ERROR_FTP_PROTOCOL_SERVICE_NOT_AVAILABLE_CLOSING_CONTROL_CONNECTION
    ERROR_FTP_PROTOCOL_CANNOT_OPEN_DATA_CONNECTION
    ERROR_FTP_PROTOCOL_CONNECTION_CLOSED_TRANSFER_ABORTED
    ERROR_FTP_PROTOCOL_REQUESTED_FILE_ACTION_NOT_TAKEN
    ERROR_FTP_PROTOCOL_REQUESTED_ACTION_ABORTED
    ERROR_FTP_PROTOCOL_REQUESTED_ACTION_NOT_TAKEN
    ERROR_FTP_PROTOCOL_SYNTAX_ERROR_COMMAND_UNRECOGNIZED
    ERROR_FTP_PROTOCOL_SYNTAX_ERROR_IN_PARAMETERS_OR_ARGUMENTS
    ERROR_FTP_PROTOCOL_COMMAND_NOT_IMPLEMENTED
    ERROR_FTP_PROTOCOL_BAD_SEQUENCE_OF_COMMANDS
    ERROR_FTP_PROTOCOL_COMMAND_NOT_IMPLEMENTED_FOR_THAT_PARAMETER
    ERROR_FTP_PROTOCOL_NOT_LOGGED_IN
    ERROR_FTP_PROTOCOL_NEED_ACCOUNT_FOR_STORING_FILES
    ERROR_FTP_PROTOCOL_REQUESTED_ACTION_NOT_TAKEN_FILE_UNAVAILABLE
    ERROR_FTP_PROTOCOL_REQUESTED_ACTION_ABORTED_PAGE_TYPE_UNKNOWN
    ERROR_FTP_PROTOCOL_REQUESTED_FILE_ACTION_ABORTED_EXCEEDED_STORAGE_ALLOCATION
    ERROR_FTP_PROTOCOL_REQUESTED_ACTION_NOT_TAKEN_FILE_NAME_NOT_ALLOWED
    ERROR_FTP_USER_TIMEOUT
    ERROR_FTP_USER_TRANSFER_IN_PROGRESS
End Enum

'********************************************************************************
'定义类事件
'********************************************************************************
Public Event StateChanged(State As FTP_CONNECTION_STATES)
Public Event DownloadProgress(lBytes As Long)
Public Event UploadProgress(lBytes As Long)
Public Event ReplyMessage(ByVal sMessage As String)
'********************************************************************************
'类模块内部的变量和常数
'********************************************************************************
Const RESPONSE_CODE_LENGHT = 3
Private m_LastError             As FtpErrors
Private m_strLastErrorDesc      As String
Private m_strWinsockBuffer      As String
Private m_strDataBuffer         As String
Private m_strLocalFilePath      As String
Private m_intLocalFileID        As Integer
Private m_bTransferInProgress   As Boolean
Private m_lDownloadedBytes      As Long
Private m_bUploadFile           As Boolean
Private m_lUploadedBytes        As Long
Private m_strLastServerResponse As String
Private m_objTimeOut            As CTimeout
Private m_bFileIsOpened         As Boolean

Public Function FtpGetLastError() As FtpErrors
'获得最近一次错误的函数
    FtpGetLastError = m_LastError
End Function
Public Function CurrentDirectory() As String
'获得当前目录的函数
    CurrentDirectory = m_strCurrentDirectory
End Function
Public Function GetLastServerResponse() As String
'获得最近一次服务器响应的函数
    GetLastServerResponse = m_strLastServerResponse
End Function
Public Property Get TransferMode() As FtpTransferModes
'传输模式属性
    TransferMode = m_TransferMode
End Property
Public Property Let TransferMode(NewValue As FtpTransferModes)
'改变传输模式属性
    m_bBusy = True
    If Not (NewValue = m_TransferMode) Then
        If ProcessTYPECommand(NewValue) Then
            m_TransferMode = NewValue
        End If
    End If
    m_bBusy = False
End Property

Private Function ProcessLISTCommand() As Boolean
'********************************************************************************
'该函数的功能是向服务器发送LIST命令
'list的功能是获得指定目录中的字目录、文件列表或者是指定文件的信息
'modified by wxp
'Date   2000-11
'********************************************************************************

On Error GoTo ProcessLISTCommand_Err_Handler

    Dim strResponse As String
    Dim strData     As String

    wscControl.SendData "LIST" & vbCrLf
    Debug.Print "LIST"
    RaiseEvent ReplyMessage("LIST")
    
    m_objTimeOut.StartTimer
    Do
        DoEvents
        '
        If m_objTimeOut.Timeout Then
            m_LastError = ERROR_FTP_USER_TIMEOUT
            Exit Do
        End If
        '
        If InStr(1, m_strWinsockBuffer, vbCrLf) > 0 Then
            If GetResponseCode(m_strWinsockBuffer) = 150 Or _
                GetResponseCode(m_strWinsockBuffer) = 125 Then
                '忽略150返回码
                m_strWinsockBuffer = Mid$(m_strWinsockBuffer, InStr(1, m_strWinsockBuffer, vbCrLf) 2)
            Else
                strData = m_strWinsockBuffer
                m_strWinsockBuffer = ""
                Exit Do
            End If
        End If
    Loop
    m_objTimeOut.StopTimer
    
    If GetResponseCode(strData) = FTP_RESPONSE_CLOSING_DATA_CONNECTION Or _
        GetResponseCode(strData) = FTP_RESPONSE_REQUESTED_FILE_ACTION_OK_COMPLETED Then
        
        ProcessLISTCommand = True
    Else
        ProcessFtpResponse GetResponseCode(strData)
    End If
    
Exit_Label:
    Exit Function

ProcessLISTCommand_Err_Handler:
    If Not ProcessWinsockError(Err.Number, Err.Description) Then
        Err.Raise vbObjectError 1000 Err.Number, "CFtpConnection.ProcessLISTCommand", Err.Description
    End If
    GoTo Exit_Label
    
End Function

Public Property Get PassiveMode() As Boolean
'获取连接模式属性
    PassiveMode = m_bPassiveMode
End Property

Public Property Let PassiveMode(NewValue As Boolean)
'设置连接模式属性
    m_bPassiveMode = NewValue
End Property

Public Function EnumFiles(oFiles As CFtpFiles) As Boolean
'********************************************************************************
'该函数的功能是获得当前目录下面的所有目录和文件
'modified by wxp
'Date  2000-10
'********************************************************************************

Dim bDataConnectionEstablished As Boolean

'On Error GoTo EnumFiles_Err_Handler

    m_bBusy = True

    If m_bPassiveMode Then
        '如果是被动模式
        bDataConnectionEstablished = ProcessPASVCommand
    Else
        '否则发送port命令
        bDataConnectionEstablished = ProcessPORTCommand
    End If
    
    If bDataConnectionEstablished Then
        RaiseEvent StateChanged(FTP_RETRIEVING_DIRECTORY_INFO)
        If ProcessLISTCommand Then
            m_objTimeOut.StartTimer
            Do
                DoEvents
                '如果超时
                If m_objTimeOut.Timeout Then
                    m_LastError = ERROR_FTP_USER_TIMEOUT
                    '如果已经从服务器获得全部信息
                    If GetResponseCode(Left(m_strLastServerResponse, 3)) = FTP_RESPONSE_CLOSING_DATA_CONNECTION Then
                        Set oFiles = GetFileList(m_strDataBuffer)
                        EnumFiles = True
                        RaiseEvent StateChanged(FTP_DIRECTORY_INFO_COMPLETED)
                        m_strDataBuffer = ""
                    End If
                    Exit Do
                End If
                '如果已经关闭连接,表示也已经成功得到信息
                If wscData.State = sckClosing Or wscData.State = sckClosed Then
                    Set oFiles = Nothing
                    Set oFiles = GetFileList(m_strDataBuffer)
                    EnumFiles = True
                    RaiseEvent StateChanged(FTP_DIRECTORY_INFO_COMPLETED)
                    m_strDataBuffer = ""
                    Exit Do
                End If
            Loop
            m_objTimeOut.StopTimer
        Else
            '产生错误,不能建立连接
        End If
    Else
        '产生错误,不能建立连接
    End If

Exit_Label:
    m_bBusy = False
    Exit Function

EnumFiles_Err_Handler:
    Err.Raise vbObjectError 1000 Err.Number, "CFtpConnection.EnumFiles", Err.Description
    GoTo Exit_Label
End Function

Public Function SetCurrentDirectory(strNewDirectory As String) As Boolean
'设置当前目录
    m_bBusy = True
    SetCurrentDirectory = ProcessCWDCommand(strNewDirectory)
    m_bBusy = False
    
End Function

Public Property Get FtpServer() As Variant
'获得服务器地址属性
    FtpServer = m_varFtpServer
End Property

Public Property Let FtpServer(NewValue As Variant)
'设定服务器地址属性
    m_varFtpServer = NewValue
End Property

Public Property Get Password() As String
'获得密码属性
    Password = m_strPassword
End Property

Public Property Let Password(NewValue As String)
'设置密码属性
    m_strPassword = NewValue
End Property

Public Property Get UserName() As String
'获得用户名属性
    UserName = m_strUserName
End Property

Public Property Let UserName(NewValue As String)
'设置用户名属性
    m_strUserName = NewValue
End Property

Public Function Connect() As Boolean
'********************************************************************************
'该函数的功能是连接ftp服务器
'modified by wxp
'Date   2000-11
'********************************************************************************

On Error GoTo Connect_Err_Handler

Dim strData     As String

m_strWinsockBuffer = ""
m_bBusy = True

If Len(m_varFtpServer) > 0 Then
    With wscControl
        .Close
        .LocalPort = 0
        .Connect m_varFtpServer, 21
        m_objTimeOut.StartTimer
        Do
            DoEvents
            If m_objTimeOut.Timeout Then
            '如果连接超时
                m_LastError = ERROR_FTP_USER_TIMEOUT
                Exit Do
            End If
            If .State = sckConnected Then
            '如果连接成功
                m_objTimeOut.StopTimer
                RaiseEvent StateChanged(FTP_CONNECTION_CONNECTED)
                m_objTimeOut.StartTimer
                Do
                    DoEvents
                    If m_objTimeOut.Timeout Then
                    '如果超时
                        m_LastError = ERROR_FTP_USER_TIMEOUT
                        Exit Do
                    End If
                    '
                    If Len(m_strWinsockBuffer) > (RESPONSE_CODE_LENGHT - 1) Then
                        strData = m_strWinsockBuffer
                        m_strWinsockBuffer = ""
                        Exit Do
                    End If
                Loop
                m_objTimeOut.StopTimer
                Select Case GetResponseCode(strData)
                    Case FTP_RESPONSE_SERVICE_READY_FOR_NEW_USER
                    '如果是220,表示服务已经为新用户准备好
                        Select Case ProcessUSERCommand
                            Case FTP_RESPONSE_USER_LOGGED_IN
                             '如果为230,表示登录成功
                               Connect = True
                            Case FTP_RESPONSE_USER_NAME_OK_NEED_PASSWORD
                            '如果是需要密码验证,则下一步进行密码验证
                                If ProcessPASSCommand = FTP_RESPONSE_USER_LOGGED_IN Then
                                    Connect = True
                                End If
                        End Select
                        If Connect Then
                        '如果登陆成功,则获得当前工作目录
                            Call ProcessPWDCommand
                        End If
                    Case FTP_RESPONSE_SERVICE_READY_IN_MINUTES
                    '如果是120,表示服务器将在nnn分钟后准备好
                        m_LastError = ERROR_FTP_PROTOCOL_SERVICE_READY_IN_MINUTES
                    Case FTP_RESPONSE_SERVICE_NOT_AVAILABLE_CLOSING_CONTROL_CONNECTION
                    '如果是421表示服务不可用,关闭连接
                        m_LastError = ERROR_FTP_PROTOCOL_SERVICE_NOT_AVAILABLE_CLOSING_CONTROL_CONNECTION
                End Select
                Exit Do
            ElseIf .State = sckConnectAborted Then
                m_LastError = ERROR_FTP_WINSOCK_ConnectAborted
            ElseIf .State = sckResolvingHost Then
                RaiseEvent StateChanged(FTP_CONNECTION_RESOLVING_HOST)
            ElseIf .State = sckHostResolved Then
                RaiseEvent StateChanged(FTP_CONNECTION_HOST_RESOLVED)
            End If
        Loop
        m_objTimeOut.StopTimer
    End With
Else
    '产生错误
    Connect = False
    Exit Function
End If

Exit_Label:
    If Connect Then RaiseEvent StateChanged(FTP_USER_LOGGED)
    m_bBusy = False
    Exit Function

Connect_Err_Handler:
    If Not ProcessWinsockError(Err.Number, Err.Description) Then
        Err.Raise vbObjectError 1000 Err.Number, "CFtpConnection.Connect", Err.Description
    End If
    GoTo Exit_Label
    
End Function
'类初始化的时候给一些对象变量赋值
Private Sub Class_Initialize()

    Set wscControl = New MSWinsockLib.Winsock
    Set wscData = New MSWinsockLib.Winsock
    Set m_objTimeOut = New CTimeout

End Sub

Private Function GetResponseCode(strResponse As String) As Integer
'获得服务器的响应码
    If Len(strResponse) > (RESPONSE_CODE_LENGHT - 1) Then
        GetResponseCode = CInt(Left$(strResponse, 3))
    End If
        
End Function

'该函数的作用是用户登陆,进行用户名验证
Private Function ProcessUSERCommand() As FTP_RESPONSE_CODES

    Dim strData     As String
    
    On Error GoTo ProcessUSERCommand_Err_Handler
    
    RaiseEvent StateChanged(FTP_CONNECTION_AUTHENTICATION)

    m_strUserName = IIf(Len(m_strUserName) > 0, m_strUserName, "anonymous")
    
    If Len(m_strPassword) = 0 Then
        If m_strUserName = "anonymous" Then
            m_strPassword = "guest@unknown.com"
        Else
            '产生错误,退出该函数
            'Exit Function
        End If
    End If
    '发送用户名
    wscControl.SendData "USER " & m_strUserName & vbCrLf
    Debug.Print "USER " & m_strUserName
    RaiseEvent ReplyMessage("USER " & m_strUserName & vbCrLf)
    
    m_objTimeOut.StartTimer
    Do
        DoEvents
        '
        If m_objTimeOut.Timeout Then
            m_LastError = ERROR_FTP_USER_TIMEOUT
            Exit Do
        End If
        '
        If Len(m_strWinsockBuffer) > RESPONSE_CODE_LENGHT Then
            strData = m_strWinsockBuffer
            m_strWinsockBuffer = ""
            Exit Do
        End If
    Loop
    m_objTimeOut.StopTimer
    
    Select Case GetResponseCode(strData)
        '如果是230,表示用户登录成功,继续
        Case FTP_RESPONSE_USER_LOGGED_IN
            ProcessUSERCommand = FTP_RESPONSE_USER_LOGGED_IN
        '表示用户名正确,需要密码验证
        Case FTP_RESPONSE_USER_NAME_OK_NEED_PASSWORD
            ProcessUSERCommand = FTP_RESPONSE_USER_NAME_OK_NEED_PASSWORD
        Case Else
            ProcessFtpResponse GetResponseCode(strData)
    End Select
    
Exit_Label:
    Exit Function

ProcessUSERCommand_Err_Handler:
    If Not ProcessWinsockError(Err.Number, Err.Description) Then
        Err.Raise vbObjectError 1000 Err.Number, "CFtpConnection.ProcessUSERCommand", Err.Description
    End If
    GoTo Exit_Label
    
End Function
'该函数是进行密码验证
Private Function ProcessPASSCommand() As FTP_RESPONSE_CODES

    Dim strResponse As String
    Dim strData     As String
    '
    On Error GoTo ProcessPASSCommand_Err_Handler
    '向服务器发送密码
    wscControl.SendData "PASS " & m_strPassword & vbCrLf
    Debug.Print "PASS " & m_strPassword
    RaiseEvent ReplyMessage("PASS " & "**********" & vbCrLf)
    
    m_objTimeOut.StartTimer
    Do
        DoEvents
        '
        If m_objTimeOut.Timeout Then
            m_LastError = ERROR_FTP_USER_TIMEOUT
            Exit Do
        End If
        '
        If Len(m_strWinsockBuffer) > RESPONSE_CODE_LENGHT Then
            strData = m_strWinsockBuffer
            Exit Do
        End If
    Loop
    m_objTimeOut.StopTimer

    If GetResponseCode(strData) = FTP_RESPONSE_USER_LOGGED_IN Then
        Do
            DoEvents
            If InStr(1, m_strWinsockBuffer, "230 ") > 0 Then
                ProcessPASSCommand = FTP_RESPONSE_USER_LOGGED_IN
                m_strWinsockBuffer = ""
                Exit Function
            End If
        Loop
    Else
        ProcessFtpResponse GetResponseCode(strData)
    End If
    ProcessPASSCommand = GetResponseCode(strData)
    
Exit_Label:
    Exit Function

ProcessPASSCommand_Err_Handler:
    If Not ProcessWinsockError(Err.Number, Err.Description) Then
        Err.Raise vbObjectError 1000 Err.Number, "CFtpConnection.ProcessPASSCommand", Err.Description
    End If
    GoTo Exit_Label
    
End Function
'该函数是获得当前工作目录的名称
Private Function ProcessPWDCommand() As Boolean

    Dim strResponse As String
    Dim strData     As String
    
    On Error GoTo ProcessPWDCommand_Err_Handler

    wscControl.SendData "PWD" & vbCrLf
    Debug.Print "PWD"
    RaiseEvent ReplyMessage("PWD" & vbCrLf)
    
    m_objTimeOut.StartTimer
    Do
        DoEvents
        If m_objTimeOut.Timeout Then
            m_LastError = ERROR_FTP_USER_TIMEOUT
            Exit Do
        End If
        If InStr(1, m_strWinsockBuffer, vbCrLf) > 0 Then
        '当从服务器中得到的响应码中含有回车的时候,表示获得目录
            strData = m_strWinsockBuffer
            m_strWinsockBuffer = ""
            Exit Do
        End If
    Loop
    m_objTimeOut.StopTimer

    If GetResponseCode(strData) = FTP_RESPONSE_PATHNAME_CREATED Then
    '如果响应码为257,表示已经创建"PATHNAME"
        Dim intPosA As Integer, intPosB As Integer
        intPosA = InStr(1, strData, Chr$(34)) 1
        intPosB = InStr(intPosA, strData, Chr$(34))
        If intPosA > 1 And intPosB > 0 Then
            m_strCurrentDirectory = Mid$(strData, intPosA, intPosB - intPosA)
            ProcessPWDCommand = True
        Else
            '未知的响应格式
        End If
    Else
        ProcessFtpResponse GetResponseCode(strData)
    End If
    
Exit_Label:
    Exit Function

ProcessPWDCommand_Err_Handler:
    If Not ProcessWinsockError(Err.Number, Err.Description) Then
        Err.Raise vbObjectError 1000 Err.Number, "CFtpConnection.ProcessPWDCommand", Err.Description
    End If
    GoTo Exit_Label
        
End Function

Private Sub Class_Terminate()
'类结束的时候,释放资源
    '关闭连接
    Call BreakeConnection
    Set wscData = Nothing
    Set wscControl = Nothing
    
    m_objTimeOut.StopTimer
    Set m_objTimeOut = Nothing
    
End Sub
'该事件为winsock对象的事件,用来获得从服务器端的数据,该控件主要是发送命令和接收返回码
Private Sub wscControl_DataArrival(ByVal bytesTotal As Long)
    On Error Resume Next
    Dim strData As String
    
    wscControl.GetData strData
    m_strWinsockBuffer = m_strWinsockBuffer & strData
    m_strLastServerResponse = strData
    '每次接收到数据的时候,计时器标记清0
    m_objTimeOut.Reset
    
    '返回码为426表示连接关闭,传输终止
    If GetResponseCode(strData) = 426 Then
        If m_bTransferInProgress Or m_bUploadFile Then
            wscData.Close
            Close m_intLocalFileID
            '初始化一些变量
            m_strDataBuffer = ""
            m_lDownloadedBytes = 0
            m_lUploadedBytes = 0
            m_bTransferInProgress = False
            m_bUploadFile = False
            m_bFileIsOpened = False
        End If
        wscControl.Close
        m_bBusy = False
    End If
    
    Debug.Print Left(strData, Len(strData) - 2)
    RaiseEvent ReplyMessage(Left(strData, Len(strData) - 2) & vbCrLf)
    
End Sub

Private Function ProcessPORTCommand() As Boolean
'该函数的功能是发送port命令,为数据连接指定一个ip地址和本地地址
    Dim intPort         As Integer
    Dim strIPAddress    As String
    Dim colIPAddresses  As New Collection
    Dim strSend         As String
    Dim strData         As String
    
    On Error Resume Next
    
    RaiseEvent StateChanged(FTP_ESTABLISHING_DATA_CONNECTION)
    
    Do
        intPort = GetFreePort
        If wscData.State <> sckClosed Then wscData.Close
        wscData.LocalPort = intPort
        '设置本地端口
        wscData.Listen
        If Not Err Then Exit Do
    Loop
    
    On Error GoTo ProcessPORTCommand_Err_Handler
    '
    strIPAddress = CStr(wscControl.LocalIP)
    '
    strSend = "PORT " & Replace(strIPAddress, ".", ",")
    strSend = strSend & "," & intPort \ 256 & "," & (intPort Mod 256)
    '
    strSend = strSend & vbCrLf
    
    wscControl.SendData strSend
    '向服务器发送port命令
    Debug.Print Left(strSend, Len(strSend) - 2)
    RaiseEvent ReplyMessage(Left(strSend, Len(strSend) - 2) & vbCrLf)
    
    m_objTimeOut.StartTimer
    Do
        DoEvents
        '
        If m_objTimeOut.Timeout Then
            m_LastError = ERROR_FTP_USER_TIMEOUT
            Exit Do
        End If
        '
        If InStr(1, m_strWinsockBuffer, vbCrLf) > 0 Then
            strData = m_strWinsockBuffer
            m_strWinsockBuffer = ""
            Exit Do
        End If
    Loop
    m_objTimeOut.StopTimer
    
    If GetResponseCode(strData) = FTP_RESPONSE_COMMAND_OK Then
        ProcessPORTCommand = True
        RaiseEvent StateChanged(FTP_DATA_CONNECTION_ESTABLISHED)
    Else
        ProcessFtpResponse GetResponseCode(strData)
    End If
    
Exit_Label:
    Exit Function

ProcessPORTCommand_Err_Handler:
    If Not ProcessWinsockError(Err.Number, Err.Description) Then
        Err.Raise vbObjectError 1000 Err.Number, "CFtpConnection.ProcessPORTCommand", Err.Description
    End If
    GoTo Exit_Label
        
End Function

Private Function GetFreePort() As Integer
'获得一个空闲的端口
    Static intPort As Integer
    
    If intPort = 0 Then
        intPort = 1100
    Else
        intPort = intPort 1
    End If
    
    GetFreePort = intPort
    
End Function

Private Sub wscData_ConnectionRequest(ByVal requestID As Long)
'如果采用port方式接受或者发送数据,该事件接受对方的连接
    If wscData.State <> sckClosed Then wscData.Close
    
    wscData.Accept (requestID)
    
End Sub

Private Sub wscData_DataArrival(ByVal bytesTotal As Long)
'wscData的DataArrival事件,同时得到服务器传来的数据
    '该变量用来获得字符型的数据
    Dim strData As String
    '该变量用来获得从服务器上传来的二进制数据
    Dim temparray() As Byte
    
    On Error Resume Next
    
    '如果传来的数据数为0,则退出该事件
    If bytesTotal = 0 Then Exit Sub
    
    '如果正在进行文件传输,主要是下载文件
    If m_bTransferInProgress Then
        '定义数组的大小为实际从服务器传来数据量的大小
        ReDim temparray(bytesTotal)
        wscData.GetData temparray(), vbByte
    Else
    '否则将数据存在字符型变量中
        wscData.GetData strData
    End If
    
    '如果是文件传输而且不是上载
    If m_bTransferInProgress And Not m_bUploadFile Then
        '如果文件没有打开,则需要打开文件
        If Not m_bFileIsOpened Then
            '获得一个自由的文件号
            m_intLocalFileID = FreeFile
            '以二进制文件打开文件
            Open m_strLocalFilePath For Binary As m_intLocalFileID
            
            '标志文件已经打开
            m_bFileIsOpened = True
            '初始化下载字节数为0
            m_lDownloadedBytes = 0
        End If
        
        '将数据写到文件中
        Put m_intLocalFileID, , temparray
        m_lDownloadedBytes = m_lDownloadedBytes bytesTotal

         RaiseEvent DownloadProgress(m_lDownloadedBytes)
 
    Else
        '如果不是传输文件,则把信息加入缓冲区m_strDataBuffer
        m_strDataBuffer = m_strDataBuffer & strData
    End If
    '计时器清0
    m_objTimeOut.Reset
    Exit Sub
    
End Sub

Public Function RenameFile(strOldFileName As String, strNewFileName As String) As Boolean
'该函数的功能是更改文件名
    m_bBusy = True
    If ProcessRNFRCommand(strOldFileName) Then
        If ProcessRNTOCommand(strNewFileName) Then
            RenameFile = True
        End If
    End If
    m_bBusy = False

End Function

Public Function DeleteFile(strFileName As String) As Boolean
'该函数的功能是调用删除文件函数
    m_bBusy = True
    DeleteFile = ProcessDELECommand(strFileName)
    m_bBusy = False

End Function

Public Function RemoveDirectory(strDirName As String) As Boolean
'该函数的功能是调用删除目录函数
    m_bBusy = True
    RemoveDirectory = ProcessRMDCommand(strDirName)
    m_bBusy = False
    
End Function

Public Function CreateDirectory(strDirName As String) As Boolean
'该函数的功能是调用创建目录函数
    m_bBusy = True
    CreateDirectory = ProcessMKDCommand(strDirName)
    m_bBusy = False
    
End Function

Private Function GetFileList(strListing As String) As CFtpFiles
'获得文件列表
    Dim vFiles      As Variant
    Dim vFile       As Variant
    Dim vComponents As Variant
    Dim oFtpFile    As CFtpFile
    Dim oFtpFiles   As New CFtpFiles
    
    On Error Resume Next
    '释放原来资源
    Set GetFileList = Nothing
    '传来的数据项之间都是用回车换行符隔开的,所以通过split函数分出来
    vFiles = Split(strListing, vbCrLf)
    '
    For Each vFile In vFiles
        Set oFtpFile = New CFtpFile
        For i = 15 To 2 Step -1
            vFile = Replace(vFile, Space(i), " ")
        Next
        '以下为获得文件的相关信息
        If Len(vFile) > 0 Then
            If Not LCase(Left(vFile, 5)) = "total" Then
                vComponents = Split(vFile, " ")
                If UBound(vComponents) > 7 Then
                    With oFtpFile
                        If Left(vComponents(0), 1) = "d" Then
                            oFtpFile.IsDirectory = True
                        ElseIf Left(vFile, 1) = "l" Then
                            .FilePath = vComponents(10)
                            If Not CBool(InStr(InStrRev(vComponents(10), "/") 1, vComponents(10), ".")) Then
                                .IsDirectory = True
                            End If
                        End If
                        .Permissions = vComponents(0)
                        .Owner = vComponents(2)
                        .Group = vComponents(3)
                        .FileSize = vComponents(4)
                        .FileName = vComponents(8)
                        .LastWriteTime = GetDate(vComponents(6), vComponents(5), vComponents(7))
                        If Not (.FileName = "." Or .FileName = "..") Then
                            oFtpFiles.Add oFtpFile, oFtpFile.FileName
                        End If
                    End With
                Else
                    With oFtpFile
                        If vComponents(2) = "<DIR>" Then
                            .IsDirectory = True
                        Else
                            .FileSize = CLng(vComponents(2))
                        End If
                        If UBound(vComponents) > 3 Then
                            Dim strFile As String
                            For i = 3 To UBound(vComponents)
                               strFile = strFile & " " & vComponents(i)
                            Next i
                            strFile = Mid$(strFile, 2)
                        Else
                            strFile = vComponents(3)
                        End If
                        Debug.Print "vComponents(2): " & vComponents(2), "vComponents(3): " & vComponents(3)
                        .FileName = strFile
                        .LastWriteTime = CDate(vComponents(0) & " " & vComponents(1))
                        oFtpFiles.Add oFtpFile, oFtpFile.FileName
                    End With
                End If
                Set oFtpFile = Nothing
            End If
        End If
        strFile = ""
    Next
    
    Set GetFileList = oFtpFiles
    Set oFtpFiles = Nothing
    
End Function

Private Function GetDate(vDay, vMonth, vYear) As Date
'该函数为获得日期函数
    vYear = IIf(InStr(1, vYear, ":"), Year(Now), vYear)
    
    Select Case vMonth
        Case "Jan": vMonth = 1
        Case "Feb": vMonth = 2
        Case "Mar": vMonth = 3
        Case "Apr": vMonth = 4
        Case "May": vMonth = 5
        Case "Jun": vMonth = 6
        Case "Jul": vMonth = 7
        Case "Aug": vMonth = 8
        Case "Sep": vMonth = 9
        Case "Oct": vMonth = 10
        Case "Nov": vMonth = 11
        Case "Dec": vMonth = 12
    End Select
    
    GetDate = DateSerial(CInt(vYear), CInt(vMonth), CInt(vDay))

End Function

Private Function ProcessPASVCommand() As Boolean
'该函数的功能是设置连接模式为被动模式
    Dim strResponse As String
    Dim strData     As String
    
    On Error GoTo ProcessPASVCommand_Err_Handler
    
    RaiseEvent StateChanged(FTP_ESTABLISHING_DATA_CONNECTION)

    wscControl.SendData "PASV" & vbCrLf
    Debug.Print "PASV"
    RaiseEvent ReplyMessage("PASV" & vbCrLf)
    
    m_objTimeOut.StartTimer
    Do
        DoEvents
        '如果超时
        If m_objTimeOut.Timeout Then
            m_LastError = ERROR_FTP_USER_TIMEOUT
            Exit Do
        End If
        '
        If InStr(1, m_strWinsockBuffer, vbCrLf) > 0 Then
            strData = m_strWinsockBuffer
            m_strWinsockBuffer = ""
            Exit Do
        End If
    Loop
    m_objTimeOut.StopTimer

    If GetResponseCode(strData) = FTP_RESPONSE_ENTERING_PASSIVE_MODE Then
        ProcessPASVCommand = MakePassiveDataConnection(strData)
    Else
        ProcessFtpResponse GetResponseCode(strData)
    End If

Exit_Label:
    Exit Function

ProcessPASVCommand_Err_Handler:
    If Not ProcessWinsockError(Err.Number, Err.Description) Then
        Err.Raise vbObjectError 1000 Err.Number, "CFtpConnection.ProcessPASVCommand", Err.Description
    End If
    GoTo Exit_Label

End Function

Private Function MakePassiveDataConnection(sData As String) As Boolean
'该函数是建立被动模式数据连接
    '
    Dim iPos            As Integer
    Dim iPos2           As Integer
    Dim strDataAddress  As String
    Dim strIP           As String
    Dim lPort           As Long
    '
    On Error GoTo MakePassiveDataConnection_Err_Handler
    '
    iPos = InStr(1, sData, "(") 1
    If Not CBool(iPos) Then Exit Function
    strDataAddress = Mid$(sData, iPos, InStr(1, sData, ")") - iPos)
    strDataAddress = Replace(strDataAddress, ",", ".", 1, 3)
    iPos = InStr(1, strDataAddress, ",")
    strIP = Left$(strDataAddress, iPos - 1)
    lPort = CLng(Mid$(strDataAddress, iPos 1, InStr(iPos 1, strDataAddress, ",") - iPos))
    lPort = lPort * 256
    lPort = lPort CLng(Mid$(strDataAddress, InStrRev(strDataAddress, ",") 1))
    
    wscData.Close
    wscData.LocalPort = 0
    wscData.Connect strIP, lPort
    
    m_objTimeOut.StartTimer
    Do
        DoEvents
        '
        If m_objTimeOut.Timeout Then
            m_LastError = ERROR_FTP_USER_TIMEOUT
            Exit Do
        End If
        '
        If wscData.State = sckConnected Then
            MakePassiveDataConnection = True
            RaiseEvent StateChanged(FTP_DATA_CONNECTION_ESTABLISHED)
            Debug.Print "Connecting to: " & strIP & ":" & lPort
            RaiseEvent ReplyMessage("Connecting to: " & strIP & ":" & lPort & vbCrLf)
            Exit Do
        End If
    Loop
    m_objTimeOut.StopTimer
    
Exit_Label:
    Exit Function
    
MakePassiveDataConnection_Err_Handler:
    If Not ProcessWinsockError(Err.Number, Err.Description) Then
        Err.Raise vbObjectError 1000 Err.Number, "CFtpConnection.MakePassiveDataConnection", Err.Description
    End If
    GoTo Exit_Label
    
End Function

Public Function DownloadFile(strFileName As String, strLocalFileName As String, vTransferMode As FtpTransferModes, Optional lStartPoint As Long) As Boolean
'该函数是下载文件
    Dim bDataConnectionEstablished As Boolean
    
    m_bBusy = True
    
    If ProcessTYPECommand(vTransferMode) Then
        m_TransferMode = vTransferMode
    Else
        Exit Function
    End If
    
    If m_bPassiveMode Then
        bDataConnectionEstablished = ProcessPASVCommand
    Else
        bDataConnectionEstablished = ProcessPORTCommand
    End If
    
    If bDataConnectionEstablished Then
        If lStartPoint > 0 Then
            m_lDownloadedBytes = lStartPoint
            If Not ProcessRESTCommand(lStartPoint) Then
                'can't restart download
                DownloadFile = False
                Exit Function
            End If
        End If
        m_bTransferInProgress = True
        m_strLocalFilePath = strLocalFileName   'Left(strLocalFileName, InStrRev(strLocalFileName, "\"))
        If ProcessRETRCommand(strFileName, lStartPoint) Then
            m_objTimeOut.StartTimer
            Do
                DoEvents
                '
                If m_objTimeOut.Timeout Then
                    m_LastError = ERROR_FTP_USER_TIMEOUT
                    Exit Do
                End If
                '
                If wscData.State = sckClosed Or wscData.State = sckClosing Then
                    RaiseEvent StateChanged(FTP_TRANSFER_COMLETED)
                    '关闭文件
                    Close m_intLocalFileID

                    m_bFileIsOpened = False
                    m_bTransferInProgress = False
                    m_lDownloadedBytes = 0
                    If Left$(GetLastServerResponse, 3) = "426" Then
                        m_LastError = FTP_RESPONSE_CONNECTION_CLOSED_TRANSFER_ABORTED
                        Call ProcessFtpResponse(FTP_RESPONSE_CONNECTION_CLOSED_TRANSFER_ABORTED)
                        DownloadFile = False
                    Else
                        DownloadFile = True
                    End If
                    Exit Do
                End If
            Loop
            m_objTimeOut.StopTimer
        Else
            DownloadFile = False
            m_bTransferInProgress = False
            Close #m_intLocalFileID
        End If
    End If
    
    m_bBusy = False

End Function

Private Function ProcessRETRCommand(strFileName As String, lStartPoint As Long) As Boolean
'该函数的命令是向服务器发送retr命令,让服务器给客户传送一份在路径名中指定的文件的副本
    Dim strResponse As String
    Dim strData     As String
    
    
    On Error GoTo ProcessRETRCommand_Err_Handler
    
    m_strDataBuffer = ""

    wscControl.SendData "RETR " & strFileName & vbCrLf
    Debug.Print "RETR " & strFileName
    RaiseEvent ReplyMessage("RETR " & strFileName & vbCrLf)
    m_objTimeOut.StartTimer
    AllBytes = 0
    Do
        DoEvents
        '
        If m_objTimeOut.Timeout Then
            m_LastError = ERROR_FTP_USER_TIMEOUT
            Exit Do
        End If
        '
        If Not m_bTransferInProgress Then
            strData = m_strWinsockBuffer
            Exit Do
        End If
        '
        
        If InStr(1, m_strWinsockBuffer, vbCrLf) > 0 Then
            If GetResponseCode(m_strWinsockBuffer) = 150 Or _
                GetResponseCode(m_strWinsockBuffer) = 125 Then
                If lStartPoint = 0 And FileExists(m_strLocalFilePath) Then
                    Kill m_strLocalFilePath
                End If
                
                '如果文件没有打开,则打开文件
                If Not m_bFileIsOpened Then
                    m_intLocalFileID = FreeFile
                    If Not m_bFileIsOpened Then '如果已经打开,再打开???
                        Open m_strLocalFilePath For Binary As m_intLocalFileID
                    End If
                    If lStartPoint > 0 Then
                        Seek m_intLocalFileID, lStartPoint 1
                    End If
                    m_bFileIsOpened = True
                    m_lDownloadedBytes = 0
                End If
                
                m_strWinsockBuffer = Mid$(m_strWinsockBuffer, InStr(1, m_strWinsockBuffer, vbCrLf) 2)
                RaiseEvent StateChanged(FTP_TRANSFER_STARTING)
            Else
                strData = m_strWinsockBuffer
                m_strWinsockBuffer = ""
                Exit Do
            End If
        End If
    Loop
    m_objTimeOut.StopTimer
    
    If GetResponseCode(strData) = FTP_RESPONSE_CLOSING_DATA_CONNECTION Or _
        GetResponseCode(strData) = FTP_RESPONSE_REQUESTED_FILE_ACTION_OK_COMPLETED Then
        ProcessRETRCommand = True
    Else
        ProcessFtpResponse GetResponseCode(strData)
        ProcessRETRCommand = False
    End If
    'modify by xmxoxo 2007.9.25 及时关闭
    If m_bFileIsOpened Then
        Close #m_intLocalFileID
    End If
    
    Debug.Print GetResponseCode(strData)
Exit_Label:
    Exit Function

ProcessRETRCommand_Err_Handler:
    If Not ProcessWinsockError(Err.Number, Err.Description) Then
        Err.Clear
        'Err.Raise vbObjectError 1000 Err.Number, "CFtpConnection.ProcessRETRCommand", Err.Description
    End If
    GoTo Exit_Label
        
End Function

Private Function ProcessRESTCommand(lStartPoint As Long) As Boolean
'该函数的的功能是向服务器发送rest命令,表示将从lstartpoint点开始传输文件
    Dim strResponse As String
    Dim strData     As String
    
    On Error GoTo ProcessRESTCommand_Err_Handler
    
    wscControl.SendData "REST " & lStartPoint & vbCrLf
    Debug.Print "REST " & lStartPoint
    RaiseEvent ReplyMessage("REST " & lStartPoint & vbCrLf)
    
    m_objTimeOut.StartTimer
    Do
        DoEvents
        '
        If m_objTimeOut.Timeout Then
            m_LastError = ERROR_FTP_USER_TIMEOUT
            Exit Do
        End If
        '
        If InStr(1, m_strWinsockBuffer, vbCrLf) > 0 Then
            strData = m_strWinsockBuffer
            m_strWinsockBuffer = ""
            Exit Do
        End If
    Loop
    m_objTimeOut.StopTimer

    If GetResponseCode(strData) = FTP_RESPONSE_REQUESTED_FILE_ACTION_PENDING_FURTHER_INFO Then
        ProcessRESTCommand = True
    Else
        ProcessFtpResponse GetResponseCode(strData)
    End If
    
Exit_Label:
    Exit Function

ProcessRESTCommand_Err_Handler:
    If Not ProcessWinsockError(Err.Number, Err.Description) Then
        Err.Raise vbObjectError 1000 Err.Number, "CFtpConnection.ProcessRESTCommand", Err.Description
    End If
    GoTo Exit_Label
        
End Function

Public Sub BreakeConnection()
    
    On Error Resume Next
    
    If wscData <> sckClosed Then
        wscData.Close
    Else
        wscControl.Close
    End If
    
    If m_bTransferInProgress Or m_bUploadFile Then
        Close m_intLocalFileID
        m_strDataBuffer = ""
        m_lDownloadedBytes = 0
        m_lUploadedBytes = 0
        m_bTransferInProgress = False
        m_bUploadFile = False
    End If
    m_bFileIsOpened = False
    m_bBusy = False
    m_objTimeOut.StopTimer
    
End Sub

Private Function ProcessTYPECommand(vType As FtpTransferModes) As Boolean
'该函数的功能是向服务器发送type命令,表示传输模式
    Dim strResponse As String
    Dim strData     As String
    
    On Error GoTo ProcessTYPECommand_Err_Handler
    
    wscControl.SendData "TYPE " & IIf(vType = FTP_ASCII_MODE, "A", "I") & vbCrLf
    Debug.Print "TYPE " & IIf(vType = FTP_ASCII_MODE, "A", "I")
    RaiseEvent ReplyMessage("TYPE " & IIf(vType = FTP_ASCII_MODE, "A", "I") & vbCrLf)
    
    m_objTimeOut.StartTimer
    Do
           DoEvents
        '
        If m_objTimeOut.Timeout Then
            m_LastError = ERROR_FTP_USER_TIMEOUT
            Exit Do
        End If
        '
        If InStr(1, m_strWinsockBuffer, vbCrLf) > 0 Then
            strData = m_strWinsockBuffer
            m_strWinsockBuffer = ""
            Exit Do
        End If
    Loop
    m_objTimeOut.StopTimer
    
    If GetResponseCode(strData) = FTP_RESPONSE_COMMAND_OK Then
        ProcessTYPECommand = True
    Else
        ProcessFtpResponse GetResponseCode(strData)
    End If
    
Exit_Label:
    Exit Function

ProcessTYPECommand_Err_Handler:
    If Not ProcessWinsockError(Err.Number, Err.Description) Then
        Err.Raise vbObjectError 1000 Err.Number, "CFtpConnection.ProcessTYPECommand", Err.Description
    End If
    GoTo Exit_Label
    

End Function

Private Function FileExists(strFileName As String) As Boolean
    
    On Error GoTo ERROR_HANDLER
    
    FileExists = (GetAttr(strFileName) And vbDirectory) = 0

ERROR_HANDLER:
    
End Function

Private Function ProcessDELECommand(strFileName As String) As Boolean
'该函数的功能是删除指定的文件
    Dim strResponse As String
    Dim strData     As String
    '
    On Error GoTo ProcessDELECommand_Err_Handler
    
    wscControl.SendData "DELE " & strFileName & vbCrLf
    Debug.Print "DELE " & strFileName
    RaiseEvent ReplyMessage("DELE " & strFileName & vbCrLf)
    
    m_objTimeOut.StartTimer
    Do
        DoEvents
        '
        If m_objTimeOut.Timeout Then
            m_LastError = ERROR_FTP_USER_TIMEOUT
            Exit Do
        End If
        '
        If InStr(1, m_strWinsockBuffer, vbCrLf) > 0 Then
            strData = m_strWinsockBuffer
            m_strWinsockBuffer = ""
            Exit Do
        End If
    Loop
    m_objTimeOut.StopTimer

    If GetResponseCode(strData) = FTP_RESPONSE_REQUESTED_FILE_ACTION_OK_COMPLETED Then
        ProcessDELECommand = True
    Else
        ProcessFtpResponse (GetResponseCode(strData))
    End If
    
Exit_Label:
    Exit Function
    
ProcessDELECommand_Err_Handler:
    If Not ProcessWinsockError(Err.Number, Err.Description) Then
        Err.Raise vbObjectError 1000 Err.Number, "CFtpConnection.ProcessDELECommand", Err.Description
    End If
    GoTo Exit_Label

End Function

Private Function ProcessMKDCommand(strDirName As String) As Boolean
'该函数的功能是创建新的目录
    Dim strResponse As String
    Dim strData     As String
    '
    On Error GoTo ProcessMKDCommand_Err_Handler
    
    wscControl.SendData "MKD " & strDirName & vbCrLf
    Debug.Print "MKD " & strDirName
    RaiseEvent ReplyMessage("MKD " & strDirName & vbCrLf)
    
    m_objTimeOut.StartTimer
    Do
        DoEvents
        '
        If m_objTimeOut.Timeout Then
            m_LastError = ERROR_FTP_USER_TIMEOUT
            Exit Do
        End If
        '
        If InStr(1, m_strWinsockBuffer, vbCrLf) > 0 Then
            strData = m_strWinsockBuffer
            m_strWinsockBuffer = ""
            Exit Do
        End If
    Loop
    m_objTimeOut.StopTimer

    If GetResponseCode(strData) = FTP_RESPONSE_PATHNAME_CREATED Then
        ProcessMKDCommand = True
    Else
        ProcessFtpResponse GetResponseCode(strData)
    End If

Exit_Label:
    Exit Function

ProcessMKDCommand_Err_Handler:
    If Not ProcessWinsockError(Err.Number, Err.Description) Then
        Err.Raise vbObjectError 1000 Err.Number, "CFtpConnection.ProcessMKDCommand", Err.Description
    End If
    GoTo Exit_Label
    
End Function

Private Function ProcessRMDCommand(strDirName As String) As Boolean
'该函数的功能是向服务器发送rmd命令,表示要删除一个目录
    Dim strResponse As String
    Dim strData     As String
    
    On Error GoTo ProcessRMDCommand_Err_Handler
    
    wscControl.SendData "RMD " & strDirName & vbCrLf
    Debug.Print "RMD " & strDirName
    RaiseEvent ReplyMessage("RMD " & strDirName & vbCrLf)
    
    m_objTimeOut.StartTimer
    Do
        DoEvents
        
        If m_objTimeOut.Timeout Then
            m_LastError = ERROR_FTP_USER_TIMEOUT
            Exit Do
        End If
        '
        If InStr(1, m_strWinsockBuffer, vbCrLf) > 0 Then
            strData = m_strWinsockBuffer
            m_strWinsockBuffer = ""
            Exit Do
        End If
    Loop
    m_objTimeOut.StopTimer

    If GetResponseCode(strData) = FTP_RESPONSE_REQUESTED_FILE_ACTION_OK_COMPLETED Then
        ProcessRMDCommand = True
    Else
        ProcessFtpResponse GetResponseCode(strData)
    End If
    
Exit_Label:
    Exit Function

ProcessRMDCommand_Err_Handler:
    If Not ProcessWinsockError(Err.Number, Err.Description) Then
        Err.Raise vbObjectError 1000 Err.Number, "CFtpConnection.ProcessRMDCommand", Err.Description
    End If
    GoTo Exit_Label

End Function

Private Function ProcessRNFRCommand(strFileName As String) As Boolean
'该函数的功能是向服务器发送rnfr命令,表示要重新命名一个文件名
    Dim strResponse As String
    Dim strData     As String
    
    On Error GoTo ProcessRNFRCommand_Err_Handler
    
    wscControl.SendData "RNFR " & strFileName & vbCrLf
    Debug.Print "RNFR " & strFileName
    RaiseEvent ReplyMessage("RNFR " & strFileName & vbCrLf)
    
    m_objTimeOut.StartTimer
    Do
        DoEvents
        '
        If m_objTimeOut.Timeout Then
            m_LastError = ERROR_FTP_USER_TIMEOUT
            Exit Do
        End If
        '
        If InStr(1, m_strWinsockBuffer, vbCrLf) > 0 Then
            strData = m_strWinsockBuffer
            m_strWinsockBuffer = ""
            Exit Do
        End If
    Loop
    m_objTimeOut.StopTimer

    If GetResponseCode(strData) = FTP_RESPONSE_REQUESTED_FILE_ACTION_PENDING_FURTHER_INFO Then
        ProcessRNFRCommand = True
    Else
        ProcessFtpResponse GetResponseCode(strData)
    End If

Exit_Label:
    Exit Function

ProcessRNFRCommand_Err_Handler:
    If Not ProcessWinsockError(Err.Number, Err.Description) Then
        Err.Raise vbObjectError 1000 Err.Number, "CFtpConnection.ProcessRNFRCommand", Err.Description
    End If
    GoTo Exit_Label
    
End Function

Private Function ProcessRNTOCommand(strFileName As String) As Boolean
'该函数的功能是向服务器发送rnto命令
    Dim strResponse As String
    Dim strData     As String
    
    On Error GoTo ProcessRNTOCommand_Err_Handler
    
    wscControl.SendData "RNTO " & strFileName & vbCrLf
    Debug.Print "RNTO " & strFileName
    RaiseEvent ReplyMessage("RNTO " & strFileName & vbCrLf)
    
    m_objTimeOut.StartTimer
    Do
        DoEvents
        '
        If m_objTimeOut.Timeout Then
            m_LastError = ERROR_FTP_USER_TIMEOUT
            Exit Do
        End If
        '
        If InStr(1, m_strWinsockBuffer, vbCrLf) > 0 Then
            strData = m_strWinsockBuffer
            m_strWinsockBuffer = ""
            Exit Do
        End If
    Loop
    m_objTimeOut.StopTimer

    If GetResponseCode(strData) = FTP_RESPONSE_REQUESTED_FILE_ACTION_OK_COMPLETED Then
        ProcessRNTOCommand = True
    Else
        ProcessFtpResponse GetResponseCode(strData)
    End If
    
Exit_Label:
    Exit Function

ProcessRNTOCommand_Err_Handler:
    If Not ProcessWinsockError(Err.Number, Err.Description) Then
        Err.Raise vbObjectError 1000 Err.Number, "CFtpConnection.ProcessRNTOCommand", Err.Description
    End If
    GoTo Exit_Label

End Function

Public Function UploadFile(strLocalFileName As String, strRemoteFileName As String, vTransferMode As FtpTransferModes, Optional lStartPoint As Long) As Boolean
'该函数的功能是向服务器上传数据
    Dim bDataConnectionEstablished As Boolean
        
    m_bBusy = True
        
    If Not (vTransferMode = m_TransferMode) Then
        If ProcessTYPECommand(vTransferMode) Then
            m_TransferMode = vTransferMode
        Else
            Exit Function
        End If
    End If
    
    If m_bPassiveMode Then
        bDataConnectionEstablished = ProcessPASVCommand
    Else
        bDataConnectionEstablished = ProcessPORTCommand
    End If
    
    If bDataConnectionEstablished Then
        '
        If Not IsMissing(lStartPoint) Then
            If Not ProcessRESTCommand(lStartPoint) Then
                UploadFile = False
                Exit Function
            End If
        End If
        '
        m_strLocalFilePath = strLocalFileName
        m_bUploadFile = True
        If ProcessSTORCommand(strLocalFileName, strRemoteFileName, lStartPoint) Then
            m_objTimeOut.StartTimer
            Do
                DoEvents
                '
                If m_objTimeOut.Timeout Then
                    m_LastError = ERROR_FTP_USER_TIMEOUT
                    Exit Do
                End If
                '
                If wscData.State = sckClosing Or _
                    wscData.State = sckClosed Then
                    'clear winsock buffer
                    RaiseEvent StateChanged(FTP_TRANSFER_COMLETED)
                    Exit Do
                End If
            Loop
            m_objTimeOut.StopTimer
            UploadFile = True
        End If
    End If
    
    m_bBusy = False
    
End Function

Private Function ProcessSTORCommand(strLocalFileName As String, strRemoteFileName As String, lStartPoint As Long) As Boolean
'该函数的功能是向服务器发送stor命令,让服务器准备接收一个来自数据连接的文件
    Dim strResponse As String
    Dim strData     As String
    
    On Error GoTo ProcessSTORCommand_Err_Handler
    
    m_strDataBuffer = ""

    wscControl.SendData "STOR " & strRemoteFileName & vbCrLf
    Debug.Print "STOR " & strRemoteFileName
    RaiseEvent ReplyMessage("STOR " & strRemoteFileName & vbCrLf)
    
    m_objTimeOut.StartTimer
    Do
        DoEvents
        '
        If m_objTimeOut.Timeout Then
            m_LastError = ERROR_FTP_USER_TIMEOUT
            Exit Do
        End If
        '
        If InStr(1, m_strWinsockBuffer, vbCrLf) > 0 Then
            If GetResponseCode(m_strWinsockBuffer) = 150 Or _
                GetResponseCode(m_strWinsockBuffer) = 125 Then

                m_strWinsockBuffer = ""
                RaiseEvent StateChanged(FTP_TRANSFER_STARTING)
                m_strLocalFilePath = strLocalFileName
                Call UploadData(lStartPoint)
            Else
                strData = m_strWinsockBuffer
                m_strWinsockBuffer = ""
                Exit Do
            End If
        End If
    Loop
    m_objTimeOut.StopTimer

    If GetResponseCode(strData) = FTP_RESPONSE_CLOSING_DATA_CONNECTION Or _
        GetResponseCode(strData) = FTP_RESPONSE_REQUESTED_FILE_ACTION_OK_COMPLETED Then
        ProcessSTORCommand = True
    Else
        ProcessFtpResponse GetResponseCode(strData)
    End If
    
Exit_Label:
    Exit Function

ProcessSTORCommand_Err_Handler:
    If Not ProcessWinsockError(Err.Number, Err.Description) Then
        Err.Raise vbObjectError 1000 Err.Number, "CFtpConnection.ProcessSTORCommand", Err.Description
    End If
    GoTo Exit_Label

End Function

Private Sub wscData_SendComplete()
    
    If m_bUploadFile Then
        Call UploadData(0)
    End If
    
    m_objTimeOut.Reset
    
End Sub

Private Sub wscData_SendProgress(ByVal bytesSent As Long, ByVal bytesRemaining As Long)

    m_lUploadedBytes = m_lUploadedBytes bytesSent
    
    RaiseEvent UploadProgress(m_lUploadedBytes)

End Sub

Private Sub UploadData(lStartPoint As Long)
'--------------------------------------------------------------------------------
'该函数的功能是是打开一个文件,然后把数据上传到服务器,每次传送4k字节
'modified by wxp
'date 2000-11
'说明 :如果一次传送多于4k的字节,则有可能多次产生wscFtpData_SendComplete事件
'--------------------------------------------------------------------------------
    
    Const CHANK_SIZE As Integer = 4096
    
    Static bFileIsOpen  As Boolean  '标记变量
    Static lChanksCount As Long     '总共要传送的次数
    Static lCounter     As Long     '已经传送的次数
    Static intRemainder As Integer  '
    Dim strData()         As Byte   '用来存放被发送的数据
    
    On Error GoTo UploadData_Err_Handler
    '如果 bFileIsOpen = True,则表示文件已经被打开了
    If m_bFileIsOpened Then
        '上传下一个数据包
        If lCounter < lChanksCount And lCounter > 0 Then
            '首先开辟一个4k的缓存
            ReDim strData(CHANK_SIZE)
            '计数器加一
            lCounter = lCounter 1
            '从文件中读去数据到strdata中
            Get m_intLocalFileID, , strData()
            '发送数据
            wscData.SendData strData()
        Else
            '所有的数据已经上载
            If lCounter = 0 Then
                '
                '关闭数据连接
                '连接已经完成
                '
                wscData.Close
                '
                '关闭本地文件
                '
                Close #m_intLocalFileID
                '
                RaiseEvent StateChanged(FTP_TRANSFER_COMLETED)
                '
                '初始化一些数据
                
                '
                m_lUploadedBytes = 0:       lChanksCount = 0: intRemainder = 0
                m_bFileIsOpened = False:        m_bUploadFile = False
                '
            Else
                '现在发送剩余的数据
                'now we have to send the remainder
                ReDim strData(intRemainder)
                '将计数器清0,下面是最后一批数据了
                lCounter = 0
                '从文件中读取数据
                Get m_intLocalFileID, , strData()
                '发送数据
                m_objTimeOut.StartTimer
                Do
                    DoEvents
                    '
                    If m_objTimeOut.Timeout Then
                        m_LastError = ERROR_FTP_USER_TIMEOUT
                        Exit Do
                    End If
                    '
                    If wscData.State = sckConnected Then
                        wscData.SendData strData
                        Exit Do
                    End If
                Loop
                m_objTimeOut.StopTimer
            End If
        End If
    Else
        '
        '以下是第一次发送数据,需要打开文件
        '
        m_bFileIsOpened = True  '做一个文件打开的标志
        '
        m_intLocalFileID = FreeFile
        '
        Open m_strLocalFilePath For Binary As m_intLocalFileID
        '如果开始上传的起始点大于0,则表示是发送剩余的数据,类似与断点续传
        If lStartPoint > 0 Then
            Seek m_intLocalFileID, lStartPoint 1
            m_lUploadedBytes = lStartPoint
            '获得剩余文件大小,并计算需要分成几个数据包发送
            lChanksCount = CLng((FileLen(m_strLocalFilePath) - lStartPoint) \ CHANK_SIZE)
            '获得不完整数据包即最后一个数据包的大小
            intRemainder = (FileLen(m_strLocalFilePath) - lStartPoint) Mod CHANK_SIZE
        Else
            '
            '如果是上传整个文件,则计算完整的数据包的个数
            lChanksCount = CLng(FileLen(m_strLocalFilePath) \ CHANK_SIZE)
            '
            '获得剩余字节
            intRemainder = FileLen(m_strLocalFilePath) Mod CHANK_SIZE
        End If

        
        If lChanksCount = 0 Then
            '如果整个文件不足一个完整的数据包,即4k,则创建一个实际文件大小的缓存区
            
            ReDim strData(intRemainder)
        Else
            '
            '否则创建一个4k大小的内存空间
            ReDim strData(CHANK_SIZE)
            '将发送数据包的计数器设置为1
            lCounter = 1
        End If
        
        '从文件中读取数据
        Get m_intLocalFileID, , strData
        '发送数据
                Do
                    DoEvents
                    If wscData.State = sckConnected Then
                        wscData.SendData strData
                        Exit Do
                    End If
                Loop
        '
    End If
    
    Exit Sub
    
Exit_Label:
    Exit Sub

UploadData_Err_Handler:
    If Not ProcessWinsockError(Err.Number, Err.Description) Then
        Err.Raise vbObjectError 1000 Err.Number, "CFtpConnection.UploadData", Err.Description
    End If
    Close #intFile
    GoTo Exit_Label
    
End Sub

Private Function ShowTimeOut() As Boolean

    Dim intRetVal As Integer
    
    intRetVal = MsgBox("A time-out occurred while communicating with the server." & _
                "The server took too long to respond." & vbCrLf & vbCrLf & _
                "Would you like to wait for server response?", vbYesNo vbQuestion, _
                "Time out")
    
    If intRetVal = vbYes Then
        m_objTimeOut.Reset
        m_objTimeOut.StartTimer
        ShowTimeOut = True
    End If
    
End Function

Public Property Let Timeout(NewValue As Integer)
    m_intTimeout = NewValue
    m_objTimeOut.TimeoutValue = NewValue
End Property

Public Property Get Timeout() As Integer
    Timeout = m_intTimeout
End Property

Public Property Get Busy() As Boolean
    Busy = m_bBusy
End Property

Private Function ProcessWinsockError(intError As ErrorConstants, strDesc As String) As Boolean
'该函数的功能处理winsock通讯时的错误
    m_strLastErrorDesc = strDesc
    
    Select Case intError
        Case sckAddressInUse
            m_LastError = ERROR_FTP_WINSOCK_AddressInUse
        Case sckAddressNotAvailable
            m_LastError = ERROR_FTP_WINSOCK_AddressNotAvailable
        Case sckAlreadyComplete
            m_LastError = ERROR_FTP_WINSOCK_AlreadyComplete
        Case sckAlreadyConnected
            m_LastError = ERROR_FTP_WINSOCK_AlreadyConnected
        Case sckBadState
            m_LastError = ERROR_FTP_WINSOCK_BadState
        Case sckConnectAborted
            m_LastError = ERROR_FTP_WINSOCK_ConnectAborted
        Case sckConnectionRefused
            m_LastError = ERROR_FTP_WINSOCK_ConnectionRefused
        Case sckConnectionReset
            m_LastError = ERROR_FTP_WINSOCK_ConnectionReset
        Case sckGetNotSupported
            m_LastError = ERROR_FTP_WINSOCK_GetNotSupported
        Case sckHostNotFound
            m_LastError = ERROR_FTP_WINSOCK_HostNotFound
        Case sckHostNotFoundTryAgain
            m_LastError = ERROR_FTP_WINSOCK_HostNotFoundTryAgain
        Case sckInProgress
            m_LastError = ERROR_FTP_WINSOCK_InProgress
        Case sckInvalidArg
            m_LastError = ERROR_FTP_WINSOCK_InvalidArg
        Case sckInvalidArgument
            m_LastError = ERROR_FTP_WINSOCK_InvalidArgument
        Case sckInvalidOp
            m_LastError = ERROR_FTP_WINSOCK_InvalidOp
        Case sckInvalidPropertyValue
            m_LastError = ERROR_FTP_WINSOCK_InvalidPropertyValue
        Case sckMsgTooBig
            m_LastError = ERROR_FTP_WINSOCK_MsgTooBig
        Case sckNetReset
            m_LastError = ERROR_FTP_WINSOCK_NetReset
        Case sckNetworkSubsystemFailed
            m_LastError = ERROR_FTP_WINSOCK_NetworkSubsystemFailed
        Case sckNetworkUnreachable
            m_LastError = ERROR_FTP_WINSOCK_NetworkUnreachable
        Case sckNoBufferSpace
            m_LastError = ERROR_FTP_WINSOCK_NoBufferSpace
        Case sckNoData
            m_LastError = ERROR_FTP_WINSOCK_NoData
        Case sckNonRecoverableError
            m_LastError = ERROR_FTP_WINSOCK_NonRecoverableError
        Case sckNotConnected
            m_LastError = ERROR_FTP_WINSOCK_NotConnected
        Case sckNotInitialized
            m_LastError = ERROR_FTP_WINSOCK_NotInitialized
        Case sckNotSocket
            m_LastError = ERROR_FTP_WINSOCK_NotSocket
        Case sckOpCanceled
            m_LastError = ERROR_FTP_WINSOCK_OpCanceled
        Case sckOutOfMemory
            m_LastError = ERROR_FTP_WINSOCK_OutOfMemory
        Case sckOutOfRange
            m_LastError = ERROR_FTP_WINSOCK_OutOfRange
        Case sckPortNotSupported
            m_LastError = ERROR_FTP_WINSOCK_PortNotSupported
        Case sckSetNotSupported
            m_LastError = ERROR_FTP_WINSOCK_SetNotSupported
        Case sckSocketShutdown
            m_LastError = ERROR_FTP_WINSOCK_SocketShutdown
        Case sckSuccess
            m_LastError = ERROR_FTP_WINSOCK_Success
        Case sckTimedout
            m_LastError = ERROR_FTP_WINSOCK_Timedout
        Case sckUnsupported
            m_LastError = ERROR_FTP_WINSOCK_Unsupported
        Case sckWouldBlock
            m_LastError = ERROR_FTP_WINSOCK_WouldBlock
        Case sckWrongProtocol
            m_LastError = ERROR_FTP_WINSOCK_WrongProtocol
    Case Else
        ProcessWinsockError = False
        Exit Function
    End Select
    
    ProcessWinsockError = True
    
End Function

Private Function ProcessFtpResponse(intCode As FTP_RESPONSE_CODES) As Boolean
'该函数的功能是对各种响应码进行分析
    Select Case intCode
        Case FTP_RESPONSE_RESTATRT_MARKER_REPLY
        Case FTP_RESPONSE_SERVICE_READY_IN_MINUTES
        Case FTP_RESPONSE_DATA_CONNECTION_ALREADY_OPEN
        Case FTP_RESPONSE_FILE_STATUS_OK
        Case FTP_RESPONSE_COMMAND_OK
        Case FTP_RESPONSE_COMMAND_NOT_IMPLEMENTED_SUPERFLUOUS_AT_THIS_SITE
        Case FTP_RESPONSE_SYSTEM_STATUS_OR_SYSTEM_HELP_REPLY
        Case FTP_RESPONSE_DIRECTORY_STATUS
        Case FTP_RESPONSE_FILE_STATUS
        Case FTP_RESPONSE_HELP_MESSAGE
        Case FTP_RESPONSE_NAME_SYSTEM_TYPE
        Case FTP_RESPONSE_SERVICE_READY_FOR_NEW_USER
        Case FTP_RESPONSE_SERVICE_CLOSING_CONTROL_CONNECTION
        Case FTP_RESPONSE_DATA_CONNECTION_OPEN
        Case FTP_RESPONSE_CLOSING_DATA_CONNECTION
        Case FTP_RESPONSE_ENTERING_PASSIVE_MODE
        Case FTP_RESPONSE_USER_LOGGED_IN
        Case FTP_RESPONSE_REQUESTED_FILE_ACTION_OK_COMPLETED
        Case FTP_RESPONSE_PATHNAME_CREATED
        Case FTP_RESPONSE_USER_NAME_OK_NEED_PASSWORD
            m_LastError = ERROR_FTP_PROTOCOL_USER_NAME_OK_NEED_PASSWORD
        Case FTP_RESPONSE_NEED_ACCOUNT_FOR_LOGIN
            m_LastError = ERROR_FTP_PROTOCOL_NEED_ACCOUNT_FOR_LOGIN
        Case FTP_RESPONSE_REQUESTED_FILE_ACTION_PENDING_FURTHER_INFO
            m_LastError = ERROR_FTP_PROTOCOL_REQUESTED_FILE_ACTION_PENDING_FURTHER_INFO
        Case FTP_RESPONSE_SERVICE_NOT_AVAILABLE_CLOSING_CONTROL_CONNECTION
            m_LastError = ERROR_FTP_PROTOCOL_SERVICE_NOT_AVAILABLE_CLOSING_CONTROL_CONNECTION
            m_strLastErrorDesc = "Service not available, closing control connection."
        Case FTP_RESPONSE_CANNOT_OPEN_DATA_CONNECTION
            m_strLastErrorDesc = "Can't open data connection."
            m_LastError = ERROR_FTP_PROTOCOL_CANNOT_OPEN_DATA_CONNECTION
        Case FTP_RESPONSE_CONNECTION_CLOSED_TRANSFER_ABORTED
            m_strLastErrorDesc = "Connection closed; transfer aborted."
            m_LastError = ERROR_FTP_PROTOCOL_CONNECTION_CLOSED_TRANSFER_ABORTED
        Case FTP_RESPONSE_REQUESTED_FILE_ACTION_NOT_TAKEN
            m_strLastErrorDesc = "Requested file action not taken."
            m_LastError = ERROR_FTP_PROTOCOL_REQUESTED_ACTION_NOT_TAKEN
        Case FTP_RESPONSE_REQUESTED_ACTION_ABORTED
            m_strLastErrorDesc = "Requested action aborted: local error in processing."
            m_LastError = ERROR_FTP_PROTOCOL_REQUESTED_ACTION_ABORTED
        Case FTP_RESPONSE_REQUESTED_ACTION_NOT_TAKEN
            m_LastError = ERROR_FTP_PROTOCOL_REQUESTED_ACTION_NOT_TAKEN
            m_strLastErrorDesc = "Requested action not taken. Insufficient storage space in system."
        Case FTP_RESPONSE_SYNTAX_ERROR_COMMAND_UNRECOGNIZED
            m_strLastErrorDesc = "Syntax error, command unrecognized."
            m_LastError = ERROR_FTP_PROTOCOL_SYNTAX_ERROR_COMMAND_UNRECOGNIZED
        Case FTP_RESPONSE_SYNTAX_ERROR_IN_PARAMETERS_OR_ARGUMENTS
            m_strLastErrorDesc = "Syntax error in parameters or arguments."
            m_LastError = ERROR_FTP_PROTOCOL_SYNTAX_ERROR_IN_PARAMETERS_OR_ARGUMENTS
        Case FTP_RESPONSE_COMMAND_NOT_IMPLEMENTED
            m_strLastErrorDesc = "Command not implemented."
            m_LastError = ERROR_FTP_PROTOCOL_COMMAND_NOT_IMPLEMENTED
        Case FTP_RESPONSE_BAD_SEQUENCE_OF_COMMANDS
            m_strLastErrorDesc = "Bad sequence of commands."
            m_LastError = ERROR_FTP_PROTOCOL_BAD_SEQUENCE_OF_COMMANDS
        Case FTP_RESPONSE_COMMAND_NOT_IMPLEMENTED_FOR_THAT_PARAMETER
            m_strLastErrorDesc = "Command not implemented for that parameter."
            m_LastError = ERROR_FTP_PROTOCOL_COMMAND_NOT_IMPLEMENTED_FOR_THAT_PARAMETER
        Case FTP_RESPONSE_NOT_LOGGED_IN
            m_strLastErrorDesc = "Not logged in."
            m_LastError = ERROR_FTP_PROTOCOL_NOT_LOGGED_IN
        Case FTP_RESPONSE_NEED_ACCOUNT_FOR_STORING_FILES
            m_strLastErrorDesc = "Need account for storing files."
            m_LastError = ERROR_FTP_PROTOCOL_NEED_ACCOUNT_FOR_STORING_FILES
        Case FTP_RESPONSE_REQUESTED_ACTION_NOT_TAKEN_FILE_UNAVAILABLE
            m_strLastErrorDesc = "Requested action not taken. File unavailable (e.g., file not found, no access)."
            m_LastError = ERROR_FTP_PROTOCOL_REQUESTED_ACTION_NOT_TAKEN_FILE_UNAVAILABLE
        Case FTP_RESPONSE_REQUESTED_ACTION_ABORTED_PAGE_TYPE_UNKNOWN
            m_strLastErrorDesc = "Requested action aborted: page type unknown."
            m_LastError = ERROR_FTP_PROTOCOL_REQUESTED_ACTION_ABORTED_PAGE_TYPE_UNKNOWN
        Case FTP_RESPONSE_REQUESTED_FILE_ACTION_ABORTED_EXCEEDED_STORAGE_ALLOCATION
            m_strLastErrorDesc = "Requested file action aborted. Exceeded storage allocation (for current directory or dataset)."
            m_LastError = ERROR_FTP_PROTOCOL_REQUESTED_FILE_ACTION_ABORTED_EXCEEDED_STORAGE_ALLOCATION
        Case FTP_RESPONSE_REQUESTED_ACTION_NOT_TAKEN_FILE_NAME_NOT_ALLOWED
            m_strLastErrorDesc = "Requested action not taken. File name not allowed."
            m_LastError = ERROR_FTP_PROTOCOL_REQUESTED_ACTION_NOT_TAKEN_FILE_NAME_NOT_ALLOWED
        Case Else
            ProcessFtpResponse = False
            Exit Function
    End Select
    
    ProcessFtpResponse = True
    
End Function

Public Function GetCurrentDirectory() As String

    m_bBusy = True
    If ProcessPWDCommand Then
        GetCurrentDirectory = m_strCurrentDirectory
    End If
    m_bBusy = False
    
End Function

Private Function ProcessQUITCommand() As Boolean
'该函数的功能是向服务器发送quit命令,终止连接、注销用户
    Dim strResponse As String
    Dim strData     As String
    
    On Error GoTo ProcessQUITCommand_Err_Handler
    
    wscControl.SendData "QUIT" & vbCrLf
    Debug.Print "QUIT"
    RaiseEvent ReplyMessage("QUIT" & vbCrLf)
    
    m_objTimeOut.StartTimer
    Do
        DoEvents
        '
        If m_objTimeOut.Timeout Then
            m_LastError = ERROR_FTP_USER_TIMEOUT
            Exit Do
        End If
        '
        If InStr(1, m_strWinsockBuffer, vbCrLf) > 0 Then
            strData = m_strWinsockBuffer
            m_strWinsockBuffer = ""
            Exit Do
        End If
    Loop
    m_objTimeOut.StopTimer
    
    If GetResponseCode(strData) = FTP_RESPONSE_SERVICE_CLOSING_CONTROL_CONNECTION Then
        ProcessQUITCommand = True
    Else
        ProcessFtpResponse GetResponseCode(strData)
    End If
    
Exit_Label:
    Exit Function

ProcessQUITCommand_Err_Handler:
    If Not ProcessWinsockError(Err.Number, Err.Description) Then
        Err.Raise vbObjectError 1000 Err.Number, "CFtpConnection.ProcessQUITCommand", Err.Description
    End If
    GoTo Exit_Label
    
End Function

Private Function ProcessABORCommand() As Boolean
'该函数的功能是终止上一次ftp服务器命令及相关数据传输
    Dim strResponse As String
    Dim strData     As String
    
    On Error GoTo ProcessABORCommand_Err_Handler
    
    wscControl.SendData "ABOR" & vbCrLf
    Debug.Print "ABOR"
    RaiseEvent ReplyMessage("ABOR" & vbCrLf)
    
    m_objTimeOut.StartTimer
    Do
        DoEvents
        '
        If m_objTimeOut.Timeout Then
            m_LastError = ERROR_FTP_USER_TIMEOUT
            Exit Do
        End If
        '
        If InStr(1, m_strWinsockBuffer, vbCrLf) > 0 Then
            strData = m_strWinsockBuffer
            m_strWinsockBuffer = "226" & vbCrLf
            Exit Do
        End If
    Loop
    m_objTimeOut.StopTimer
    
    If GetResponseCode(strData) = 426 Then
        ProcessABORCommand = True
    Else
        ProcessFtpResponse GetResponseCode(strData)
    End If
    
Exit_Label:
    Exit Function

ProcessABORCommand_Err_Handler:
    If Not ProcessWinsockError(Err.Number, Err.Description) Then
        Err.Raise vbObjectError 1000 Err.Number, "CFtpConnection.ProcessABORCommand", Err.Description
    End If
    GoTo Exit_Label
    
End Function

Public Function CancelTransfer() As Boolean

    m_bBusy = True
    If ProcessABORCommand Then
        CancelTransfer = True
    End If
    If m_bTransferInProgress Or m_bUploadFile Then
        Close m_intLocalFileID
        m_strDataBuffer = ""
        m_lDownloadedBytes = 0
        m_lUploadedBytes = 0
        m_bTransferInProgress = False
        m_bUploadFile = False
    End If
    m_bFileIsOpened = False
    m_objTimeOut.StopTimer

'    wscData.Close
    m_bBusy = False
    
End Function

Public Function SetParentAsCurrentDirectory() As Boolean

    m_bBusy = True
    SetParentAsCurrentDirectory = ProcessCDUPCommand
    m_bBusy = False
    
End Function

Private Function ProcessCDUPCommand() As Boolean
'该函数的功能是把当前目录改为远程文件系统的根目录而无需改变登录、帐号信息或传输参数
    Dim strResponse As String
    Dim strData     As String
    
    On Error GoTo ProcessCDUPCommand_Err_Handler
    
    wscControl.SendData "CDUP" & vbCrLf
    Debug.Print "CDUP"
    RaiseEvent ReplyMessage("CDUP" & vbCrLf)
    
    m_objTimeOut.StartTimer
    Do
        DoEvents
        '
        If m_objTimeOut.Timeout Then
            m_LastError = ERROR_FTP_USER_TIMEOUT
            Exit Do
        End If
        '
        If InStr(1, m_strWinsockBuffer, vbCrLf) > 0 Then
            strData = m_strWinsockBuffer
            m_strWinsockBuffer = ""
            Exit Do
        End If
    Loop
    m_objTimeOut.StopTimer
    
    If GetResponseCode(strData) = FTP_RESPONSE_REQUESTED_FILE_ACTION_OK_COMPLETED Then
        ProcessCDUPCommand = True
    Else
        ProcessFtpResponse GetResponseCode(strData)
    End If
    
Exit_Label:
    Exit Function

ProcessCDUPCommand_Err_Handler:
    If Not ProcessWinsockError(Err.Number, Err.Description) Then
        Err.Raise vbObjectError 1000 Err.Number, "CFtpConnection.ProcessCDUPCommand", Err.Description
    End If
    GoTo Exit_Label
    
End Function

Private Function ProcessCWDCommand(strNewDir As String) As Boolean
'该函数的功能是改变当前目录为指定的目录
    Dim strResponse As String
    Dim strData     As String
    
    On Error GoTo ProcessCWDCommand_Err_Handler
        
    wscControl.SendData "CWD " & strNewDir & vbCrLf
    Debug.Print "CWD " & strNewDir
    RaiseEvent ReplyMessage("CWD " & strNewDir & vbCrLf)
    
    m_objTimeOut.StartTimer
    Do
        DoEvents
        '
        If m_objTimeOut.Timeout Then
            m_LastError = ERROR_FTP_USER_TIMEOUT
            Exit Do
        End If
        '
        If InStr(1, m_strWinsockBuffer, vbCrLf) > 0 Then
            strData = m_strWinsockBuffer
            m_strWinsockBuffer = ""
            Exit Do
        End If
    Loop
    m_objTimeOut.StopTimer

    If GetResponseCode(strData) = FTP_RESPONSE_REQUESTED_FILE_ACTION_OK_COMPLETED Then
        ProcessCWDCommand = True
    Else
        ProcessFtpResponse GetResponseCode(strData)
    End If
    
Exit_Label:
    Exit Function

ProcessCWDCommand_Err_Handler:
    If Not ProcessWinsockError(Err.Number, Err.Description) Then
        Err.Raise vbObjectError 1000 Err.Number, "CFtpConnection.ProcessCWDCommand", Err.Description
    End If
    GoTo Exit_Label
End Function

Public Function GetFtpErrorDescription() As String

    GetFtpErrorDescription = m_strLastErrorDesc

End Function

Public Function CloseConnection() As Boolean

    m_bBusy = True
    If m_bTransferInProgress Or m_bUploadFile Then
        m_LastError = ERROR_FTP_USER_TRANSFER_IN_PROGRESS
        m_strLastErrorDesc = "Can't close control connection. Transfer in progress."
    Else
        CloseConnection = ProcessQUITCommand
        wscData.Close
        wscControl.Close
    End If
    m_bBusy = False
    
End Function

评论

发表评论必须先登陆, 您可以 登陆 或者 注册新账号 !


在线咨询: 问题反馈
客服QQ:174666394

有问题请留言,看到后及时答复