Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations wOOdy-Soft on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Having a tough time with the Internet Transfer Control using FTP 4

Status
Not open for further replies.

BobRodes

Instructor
May 28, 2003
4,215
US
I'm having trouble with the internet transfer control. I have the following code for testing:

Option Explicit

Private Sub Command1_Click()
Inet1.Execute "ftp://xx.xx.xx.xx", "GET /test/test.txt c:\temp\test.txt"
End Sub

Private Sub Inet1_StateChanged(ByVal State As Integer)
MsgBox State
If State = 12 Or State = 11 Then Inet1.Execute "ftp://xx.xx.xx.xx", "CLOSE"
End Sub

where inet1 is an internet transfer control on the form, and xx.xx.xx.xx is a valid ftp site. The test.txt file exists also, and is 25 bytes long. I find that sometimes this code works, and more often doesn't. It always seems to establish a connection, but then sometimes transfers the file, and sometimes returns an error, and sometimes doesn't return an error and also fails to transfer the file. I have never gotten a file of 250k to transfer.

Is this control not particularly robust, or are there things I need to know about it before using it in a production application effectively? If the former, does anyone have a suggestion of how to programmatically transfer files from an ftp site to a local client?

TIA

Bob
 
WinINET.dll may be the answer to your question. Look it up at the microsoft website.

You may want to put a loop that checks to see if the download is done before moving on...

Do While Inet1.StillExecuting = True
DoEvents
Loop

hope this helps


LF
 
I tried that loop, found it in another post (maybe yours?). It didn't help. I'll look at winINET.dll.

Thanks LF

bob
 
I tried that loop, found it in another post (maybe yours?). It didn't help. I'll look at winINET.dll.

Thanks LF

bob
 
Yeah! I posted that in another Forum.

WinInet.dll is a bit more comprehensive than the simple Inet and winsock controls, but it seems to do a better job at downloading things. Unfortunately, I have not used it to get things from FTP servers. I can't wait to see how you fare with this.

LF
 
So far, I've downloaded a couple of class modules that use the dll, and have stepped through one of them. It pukes on the getftp function. I'll keep trying, and keep you posted.

Bob
 
By the way, would the fact that I'm (still) using an AOL dialup connection be causing problems? Lord knows I've had other strange things happen.

Bob
 
hmm. Concerning the AOL thing... It could have some effect if the file you are downloading is large, or if you have a slower computer, but I doubt it.

Check out this link for reference on how to go about using this dll with FTP...


Hope this helps a bit...

LF

"As far as the laws of mathematics refer to reality, they are not certain; as far as they are certain, they do not refer to reality."--Albert Einstein
 
Thanks LF. Actually, I downloaded that one last night. I'll mess with it and send feedback.

Great minds think alike...

Thanks for your help.

Bob
 
hehe, Yeah, Great minds and Google... :)
I have tried it and it seems to work ok.

My pleasure...

LF

"As far as the laws of mathematics refer to reality, they are not certain; as far as they are certain, they do not refer to reality."--Albert Einstein
 
You've tried it? If you have some code that works, can you post it?

Thanks,

Bob
 
The Source Code comes with the program from the link I posted. I personally do not have any code relating to FTP transfer; I have only dealt with HTTP transfers. Sorry I couldn't be of further assistance.

LF

"As far as the laws of mathematics refer to reality, they are not certain; as far as they are certain, they do not refer to reality."--Albert Einstein
 
That's ok, I'll write it (or swipe something) and see what happens.

Bob
 
Ok, it seems to be working. I've been able to download a couple of 256k zip files (pretty dense stuff) without a hitch. I used some code that I found on the following link:


Pretty straightforward to use. Just make a module, and a class, and cut and paste the appropriate code into each. The code is pretty basic in terms of functionality, not much error handling for example, but it gives a good starting point that I'll be able to build on.

One more thing: I was able to get it to work with an anonymous user. I didn't try anything with userids.

Thanks for your help LF. You deserve a star for all your efforts on behalf of a stranger! :)

Best regards,

Bob
 
LOL! Thanks for the star! Also, If you want to dig deeper into the WinInet.dll control, then I would suggest these links where you can download all of the function calls that pertain to this control and VB programming--Wininet.dll is mainly a C++ function-- and find other information, including sample code, about the WInInet.dll control for Visual Basic.

LF





"As far as the laws of mathematics refer to reality, they are not certain; as far as they are certain, they do not refer to reality."--Albert Einstein
 
Cool. I'll check them out if I ever have to revisit this and make it more sophisticated. In other words, if we actually start selling the application. :)

Bob
 
This is MORE than awesome! I'm working on a project now that requires me (in the not-too-distant future) to create an FTP program to upload data from a VB desktop app. I've recorded this entire conversation for future reference.

Thanks to ALL!

AMACycleLoony
 
You are very welcome! I love WinInet.dll, as there are many many cool things that can be done with it when we are limited with other methods. FTP and HTTP are only two of the many protocols that can be used with it as well... The possibilities are nearly endless! Glad I/we could help.

LF

"As far as the laws of mathematics refer to reality, they are not certain; as far as they are certain, they do not refer to reality."--Albert Einstein
 
Here's the code I used:

These declarations I put in a standard module; however they might go better in the class itself:
Code:
'***Declarations for FTP API Calls (WinInet.dll)
  
Public Const INTERNET_FLAG_RELOAD = &H80000000
Public Const INTERNET_FLAG_PASSIVE = &H8000000
 
Public Const FTP_TRANSFER_TYPE_ASCII = &H1
Public Const FTP_TRANSFER_TYPE_BINARY = &H2
 
Public Const ERROR_INTERNET_EXTENDED_ERROR = 12003
 
Public Const INTERNET_DEFAULT_FTP_PORT = 21
Public Const INTERNET_SERVICE_FTP = 1
 
Public Declare Function FtpGetFile Lib "wininet.dll" Alias "FtpGetFileA" _
(ByVal hFtpSession As Long, ByVal lpszRemoteFile As String, _
ByVal lpszNewFile As String, ByVal fFailIfExists As Boolean, _
ByVal dwFlagsAndAttributes As Long, ByVal dwFlags As Long, _
ByVal dwContext As Long) As Boolean
 
Public Declare Function FtpPutFile Lib "wininet.dll" Alias "FtpPutFileA" _
(ByVal hFtpSession As Long, ByVal lpszLocalFile As String, _
ByVal lpszRemoteFile As String, ByVal dwFlags As Long, _
ByVal dwContext As Long) As Boolean
     
Public Declare Function InternetConnect Lib "wininet.dll" Alias "InternetConnectA" _
(ByVal hInternetSession As Long, ByVal sServerName As String, _
ByVal nServerPort As Integer, ByVal sUsername As String, _
ByVal sPassword As String, ByVal lService As Long, _
ByVal lFlags As Long, ByVal lContext As Long) As Long
 
Public Declare Function InternetOpen Lib "wininet.dll" Alias "InternetOpenA" _
(ByVal sAgent As String, ByVal lAccessType As Long, ByVal sProxyName As String, _
ByVal sProxyBypass As String, ByVal lFlags As Long) As Long
 
Public Declare Function InternetGetLastResponseInfo Lib "wininet.dll" Alias "InternetGetLastResponseInfoA" ( _
lpdwError As Long, ByVal lpszBuffer As String, _
lpdwBufferLength As Long) As Boolean
 
Public Declare Function InternetCloseHandle Lib "wininet.dll" _
(ByVal hInet As Long) As Integer

Here's the code in the class module called SimpleFTP:
Code:
Option Explicit

'Information
'Address of currently connected server
Private m_strServerAddress As String
'User name used to connect to server "anonymous" for anonymous
Private m_strUserName As String
'Number of last error to occur
Private m_lErrorNumber As Long
'Description of last error to occur
Private m_strErrorInfo As String
'Name of proxy server, vbnullstring if none
Private m_strProxyName As String
 
'State flags
'Are we currently connected to a server
Private m_blIsConnected As Boolean
'Handle of current server connection
Private m_hConn As Long
'Handle of current internet session
Private m_hSession As Long
'Option flags for the current internet session: use of proxy and DNS services
Private m_lInternetOptions As Long
 
'Proxy connection options enum
Public Enum ProxyOptions
    PRECONFIG = 0   'Default
    DIRECT = 1
    PROXY = 3
End Enum
 
'Usage flags
'Close connection after file transfer is complete?
Private m_blCloseAfterXFer As Boolean
'Replace local file if it already exists or fail the transfer?
Private m_blReplaceLocal As Boolean
'Replace remote file if it already exists or fail the transfer?
Private m_blReplaceRemote As Boolean
'Close internet session when closing server connection?
Private m_blCloseInternet As Boolean
 
 
'Custom error messages
'No currently open connection for requested operation
Private Const ERR_NO_CONNECTION = vbObjectError + 2
Private Const ERR_NO_CONNECTION_INFO = "No currently open connection for requested operation."
 
'Attempt to open a new connection when one is already open
Private Const ERR_ALREADY_OPEN = vbObjectError + 3
Private Const ERR_ALREADY_OPEN_INFO = "Connection already open."
 
Public Function OpenConnection(strServerAddr As String, strUser As String, strPass As String) As Boolean
    'Opens a connection to the specified server
    'strServerAddr can be an IP address or server name, cached in ServerName property
    'strUser should be a valid user id or anonymous, cached in UserName property
    'strPass is a valid password
   
    If m_blIsConnected Then
        'Can't open a connection if we already have one open.
        m_lErrorNumber = ERR_ALREADY_OPEN
        m_strErrorInfo = ERR_ALREADY_OPEN_INFO
        OpenConnection = False
    Else
        'cache the server and user names for retrieval via read-only properties later.
        m_strServerAddress = strServerAddr
        m_strUserName = strUser
       
        'If we don't alredy have an internet session open, open one.
        If m_hSession = 0 Then
            m_hSession = InternetOpen(App.EXEName, m_lInternetOptions, m_strProxyName, vbNullString, 0)
       
            If m_hSession = 0 Then
                GetErrorInfo "OpenConnection:InternetSession"
                OpenConnection = False
               'Could not open Internet session for some reason.
                'Gotta exit sub here, otherwise InternetConnect will fail also
                Exit Function
            End If
           
        End If
       
        'Open the specified FTP server
        m_hConn = InternetConnect(m_hSession, m_strServerAddress, INTERNET_DEFAULT_FTP_PORT, _
        m_strUserName, strPass, INTERNET_SERVICE_FTP, 0, 0)
               
        If m_hConn = 0 Then
            GetErrorInfo "OpenConnection:ServerConnect"
            OpenConnection = False
            'Could not open server for some reason.
        Else
            OpenConnection = True
            m_blIsConnected = True
        End If
               
    End If
  
End Function
 
Public Function CloseConnection() As Boolean
    'Closes the current server connection, and may close the internet session
    'as well, if m_blCloseInternet is true
   
    If m_blIsConnected Then
        'Close the server connection
        m_blIsConnected = False
        CloseConnection = True
        m_strServerAddress = vbNullString
        m_strUserName = vbNullString
        InternetCloseHandle m_hConn
       
        'Close the internet session as well, if that option is set
        If m_blCloseInternet Then
            InternetCloseHandle m_hSession
        End If
       
    Else
        'Can't close a connection when there isn't one open.
        m_lErrorNumber = ERR_NO_CONNECTION
        m_strErrorInfo = ERR_NO_CONNECTION
        CloseConnection = False
    End If
   
End Function
 
Public Function GetFile(strLocalName As String, strRemoteName As String, blBinary As Boolean)
    'Downloads a file from the remote server
    'strLocalName is the full path and name the file will have locally
    'strRemoteName is the full path and name of the file on the server
    'blBinary sets binary transfer mode if true, ASCII mode if false
   
    Dim lAtts As Long       'transfer attributes
    Dim lFlags As Long      'ASCII/Binary mode
    Dim blRet As Boolean    'return value from API call
   
    'Set flags for binary/ascii transfer
    If blBinary Then
        lFlags = FTP_TRANSFER_TYPE_BINARY
    Else
        lFlags = FTP_TRANSFER_TYPE_ASCII
    End If
    'Set to always re-download the remote file
    lAtts = INTERNET_FLAG_RELOAD
   
    If Not m_blIsConnected Then
        'We'll fail if there's no open connection.
        'However, this method could be modified to accept a server address and manage
        'connections on its own. Left to you to implement if desired.
        m_lErrorNumber = ERR_NO_CONNECTION
        m_strErrorInfo = ERR_NO_CONNECTION_INFO
        Exit Function
    Else
        'Get the file
        blRet = FtpGetFile(m_hConn, strRemoteName, strLocalName, Not m_blReplaceLocal _
        , lAtts, lFlags, 0)
       
        If Not blRet Then
            GetErrorInfo "GetFile: " & strRemoteName
            GetFile = False
            'Transfer failed for some reason, get error info
        End If
       
        'Pass back the success/failure value
        GetFile = blRet
       
        'should we close connection the connection?
        If m_blCloseAfterXFer Then
            CloseConnection
        End If
       
    End If
   
End Function
 
Public Function PutFile(strLocalName As String, strRemoteName As String, blBinary As Boolean)
    'Uploads a file to the remote server
    'strLocalName is the full path and name of the local file
    'strRemoteName is the full path and name the file will have on the server
    'blBinary sets binary mode if true, ASCII mode if false
   
    Dim blRet As Boolean    'Return value from API call
    Dim lFlags As Long      'transfer flags
   
    'Set flags for binary/ascii transfer
    If blBinary Then
        lFlags = FTP_TRANSFER_TYPE_BINARY
    Else
        lFlags = FTP_TRANSFER_TYPE_ASCII
    End If
   
    If Not m_blIsConnected Then
        'We'll fail if there's no open connection.
        'However, this method could be modified to accept a server address and manage
        'connections on its own. Left to you to implement if desired.
        m_lErrorNumber = ERR_NO_CONNECTION
        m_strErrorInfo = ERR_NO_CONNECTION_INFO
        Exit Function
    Else
        'Send the file
        blRet = FtpPutFile(m_hConn, strLocalName, strRemoteName, lFlags, 0)
       
        If Not blRet Then
            GetErrorInfo "PutFile: " & strLocalName
            PutFile = False
            'Transfer failed for some reason
        End If
       
        'pass back the return value
        PutFile = blRet
       
        'Should we close the connection?
        If m_blCloseAfterXFer Then
            CloseConnection
        End If
    End If
     
End Function
 
Public Sub ClearError()
    'Clears cached error information
    m_lErrorNumber = 0
    m_strErrorInfo = vbNullString
End Sub
Public Property Get ErrorNumber() As Long
    'Returns error number of the reported error
    ErrorNumber = m_lErrorNumber
End Property
 
Public Property Get ErrorInfo() As String
    'Returns description of the last reported error
    ErrorInfo = m_strErrorInfo
End Property
 
Public Property Get UserName() As String
    'Returns the user name used to connect
    'to the currently active connection
    'if IsConnected is false, this will return vbNullString
    UserName = m_strUserName
End Property
 
Public Property Get IsConnected() As Boolean
    'Returns true if a connection is open to a server
    IsConnected = m_blIsConnected
End Property
 
Public Property Get ServerName() As String
    'Returns the name of the currently connected server
    'if IsConnected is false, returns vbNullString
    ServerName = m_strServerAddress
End Property
 
Public Property Let AutoCloseFTP(data As Boolean)
    'Sets a value controlling whether or not
    'the active FTP connection is closed after
    'each Get or Put opertation (True) or if
    'the client must handle connections manually
    '(False and the default)
    m_blCloseAfterXFer = data
End Property
Public Property Get AutoCloseFTP() As Boolean
    'Returns a value controlling whether or not
    'the active FTP connection is closed after
    'each Get or Put opertation (True) or if
    'the client must handle connections manually
    '(False and the default)
    AutoCloseFTP = m_blCloseAfterXFer
End Property
 
Public Property Let AutoCloseINET(data As Boolean)
    'Sets a value controlling whether or not the
    'active internet session is closed when a server
    'connection is closed (True and the default) or
    'if sessions stay open from the first server connection
    'for the life of the object(false).
    m_blCloseInternet = data
End Property
Public Property Get AutoCloseINET() As Boolean
    'Returns a value controlling whether or not the
    'active internet session is closed when a server
    'connection is closed (True and the default) or
    'if sessions stay open from the first server connection
    'for the life of the object(false).
    AutoCloseINET = m_blCloseInternet
End Property
 
Public Property Let ProxyName(data As String)
    'Sets the name of the proxy server we'll use
    'to connect to the internet
    If m_hSession = 0 Then
        'can't change this once we're in a session
        m_strProxyName = data
    End If
End Property
Public Property Get ProxyName() As String
    'Returns the name of the proxy server we'll use to
    'connect to the internet, default is none (vbNullString)
    ProxyName = m_strProxyName
End Property
 
Public Property Let ProxyOptions(data As ProxyOptions)
    'Sets the proxy options for the internet session
    If m_hSession = 0 Then
        'Can't change this once we're in an internet session
        m_lInternetOptions = data
    End If
End Property
Public Property Get ProxyOptions() As ProxyOptions
    ProxyOptions = m_lInternetOptions
End Property
 
Private Sub Class_Initialize()
    'By default, replace when getting and the local file exists
    m_blReplaceLocal = True
    'But fail when sending and the remote file exists.
    m_blReplaceRemote = False
    'Also leave server connections open after transfers by default
    m_blCloseAfterXFer = False
    'and close internet sessions when server connections are closed
    m_blCloseInternet = True
    'default to no proxy server
    m_strProxyName = vbNullString
    'and default to use of IE preconfigured settings
    m_lInternetOptions = PRECONFIG
End Sub
 
Private Sub GetErrorInfo(strStatus As String)
    Dim lExtErr As Long
    Dim strExtErr As String
    Dim lBuffLen As Long
   
    If Err.LastDllError = ERROR_INTERNET_EXTENDED_ERROR Then
        'get the length of the string buffer needed for the error text
        InternetGetLastResponseInfo lExtErr, vbNullString, lBuffLen
        'Create a suitably-sized string buffer
        strExtErr = String(lBuffLen + 1, 0)
        'Get the error info
        InternetGetLastResponseInfo lExtErr, strExtErr, lBuffLen
        'Strip off that annoying last null char
        strExtErr = Trim(Left(strExtErr, Len(strExtErr) - 1))
        m_strErrorInfo = "Error reported from " & strStatus & vbCrLf _
        & "Server response (if applicable): " & vbCrLf & strExtErr
        m_lErrorNumber = lExtErr
    Else
        m_lErrorNumber = Err.LastDllError
        m_strErrorInfo = vbNullString
    End If
   
       
End Sub
Private Sub Class_Terminate()
    'Close any open internet sessions
    If m_hSession <> 0 Then
        InternetCloseHandle m_hSession
    End If
   
End Sub
 
By the way, I haven't made completely clear that I got the above code from Builder.com link I provided above, and posted it with very little modification, if any.

Bob
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top