FTP2 ActiveX Events

The Chilkat FTP2 ActiveX provides the following event callbacks:

' IMPORTANT: For all callbacks, arguments named "skip" or "abort" are output-only arguments.
' These arguments may be set to 1 within the callback to either skip a
' particular file upload/download,  or abort the entire operation.

Dim WithEvents ftp As ChilkatFtp2

' Called just before a file is to be downloaded.
Private Sub ftp_BeginDownloadFile(ByVal path As String, skipFlag As Long)

End Sub

' Called just before a file is to be uploaded.
Private Sub ftp_BeginUploadFile(ByVal path As String, skipFlag As Long)

End Sub

' Called periodically to indicate the current performance.
Private Sub ftp_DownloadRate(ByVal byteCount As Long, ByVal bytesPerSec As Long)

End Sub

' Called just after a download has completed.
Private Sub ftp_EndDownloadFile(ByVal path As String, ByVal numBytes As Long)

End Sub

' Called just after an upload has completed.
Private Sub ftp_EndUploadFile(ByVal path As String, ByVal numBytes As Long)

End Sub

' Indicate percentage completed for a download.  Note: This is only called
' for cases where it is possible to know the percent complete (0 to 100).
' For directory tree synchronization methods, it is not possible to know ahead of time
' how much work is to be done, and therefore it is not possible to know a percent-compete number.
Private Sub ftp_GetProgress(ByVal pctDone As Long)

End Sub

' Indicate percentage completed for an upload.
Private Sub ftp_PutProgress(ByVal pctDone As Long)
    ProgressBar1.Value = pctDone
End Sub

' Called periodically for upload performance information.
Private Sub ftp_UploadRate(ByVal byteCount As Long, ByVal bytesPerSec As Long)

End Sub

' Called just before a remote directory is to be deleted.
Private Sub ftp_VerifyDeleteDir(ByVal path As String, skipFlag As Long)

End Sub

' Called just before a remote file is to be deleted.
Private Sub ftp_VerifyDeleteFile(ByVal path As String, skipFlag As Long)

End Sub

' Called just before a remote directory is going to be downloaded.
' Setting skip = 1 allows for entire sub-trees to be skipped.
Private Sub ftp_VerifyDownloadDir(ByVal path As String, skipFlag As Long)

End Sub

' Called just before a remote directory is going to be uploaded.
' Setting skip = 1 allows for entire sub-trees to be skipped.
Private Sub ftp_VerifyUploadDir(ByVal path As String, skipFlag As Long)

End Sub

VB6 FTP File Upload Progress Monitoring

Question:

I’ve been trying to get the progress bar in VB6 to work, based on the code on your website, but I’m having no luck.  The event isn’t even being triggered.

Answer:

Here are some things to try:

  1. Test progress monitoring with a large enough file  such that the progress does not go from 0 to 100% instantly.
  2. Use the VB6 IDE to generate the event callback method to make sure you have the naming correct.
  3. Set the SendBufferSize property to a smaller value, to get more frequent callbacks.  See the reference documentation: http://www.chilkatsoft.com/refdoc/xChilkatFtp2Ref.html
  4. Make sure your event callback function updates the UI such that the changes are rendered immediately.  For progress bar controls, setting the Value is all that is needed.  For other controls, you may need to call Refresh.

SOCKS4 proxy server sometimes rejects FTP data connection?

The FTP Extended Passive Mode (EPSV) continues to be both a solution to problems AND the cause of problems. The Chilkat FTP2 component will automatically use EPSV (as opposed to PASV) if it detects the FTP server supports EPSV. This is generally a good thing to do, and often solves problems. However, occasionally it can be the cause of problems. This is the case here:

A Chilkat customer’s SOCKS4 proxy server sometimes rejects the FTP data connection when EPSV mode is used. The solution is to set the UseEpsv property = False after connecting to the FTP server.

In general, if passive mode seems to work with FTP clients such as FileZilla, but not Chilkat, it is possible that EPSV is the culprit. Try forcibly turning EPSV off by setting the UseEpsv property = False. Then check to see if the problem is resolved.

FTP Progress Monitoring

This post points to the various examples and blog posts scattered among the chilkatsoft.com, example-code.com, and cknotes.com involving progress monitoring of  FTP uploads and downloads using the Chilkat FTP2 ActiveX, .NET component, and C++ libs.

Important for Monitoring Upload Progress: The SendBufferSize property is set to a large value (512K) to maximize performance.  Unfortunately, this usually ruins the frequency of “percent done” callbacks for upload (not downloads, just uploads).  To improve the upload “percent done” callback frequency, set the SendBufferSize property to a smaller value, such as 4K.  It may slow the upload transfer rate a bit, but it improves the progress monitoring capability.  You can experiment with different values for SendBufferSize to determine what best suits your needs.

Monitoring Download Percent-Done: Be sure to read about the AutoGetSizeForProgress and the ProgressMonSize properties in the Chilkat online reference documentation.  Depending on your FTP server, it may be necessary to set the AutoGetSizeForProgress equal to True to properly receive percent-done event callbacks.  In most cases, neither property is needed — it entirely depends on whether the FTP server provides file-size information in the intermediate response to a “RETR” FTP protocol command.

FTP2 Events in C# and VB.NET:

FTP2 Events in VB6

FTP2 Events in C++

FTP2 Events in FoxPro:

More Information:

426 Connection closed; transfer aborted.

Problem:
An FTP transfer fails with the following message found in LastErrorText:

426 Connection closed; transfer aborted

Solution:
A local firewall may be blocking the connection. Try switching between Active and Passive mode and try again.

See these examples:

ASP: Active and Passive Modes in FTP
SQL Server: Active and Passive Modes in FTP
C#: Active and Passive Modes in FTP
C++: Active and Passive Modes in FTP
MFC: Active and Passive Modes in FTP
C: Active and Passive Modes in FTP
Delphi: Active and Passive Modes in FTP
Visual FoxPro: Active and Passive Modes in FTP
Java: Active and Passive Modes in FTP
Perl: Active and Passive Modes in FTP
PHP: Active and Passive Modes in FTP
Python: Active and Passive Modes in FTP
Ruby: Active and Passive Modes in FTP
VB.NET: Active and Passive Modes in FTP
Visual Basic: Active and Passive Modes in FTP
VBScript: Active and Passive Modes in FTP

FTP Auth TLS / SSL problem caused by Firewall Restrictions

The following Chilkat FTP2 error was found by a Chilkat customer to be caused by firewall restrictions. I do not know the specifics of the firewall restrictions that caused the error, but the LastErrorText (with all customer information removed) is reproduced here to help identify this problem in the future. The important point is to see that the SSL/TLS handshake completes to the very end, at which point the FTP client sends the “FINISHED” SSL/TLS handshake message, and then the firewall closes the connection.

ChilkatLog:
  Connect:
    DllDate: Jun 10 2010
    UnlockPrefix: ****
    Username: ****
    Component: Visual C++ 8.0
    ImplicitSsl: 0
    AuthTls: 1
    AuthSsl: 0
    Hostname: ****
    Port: 21
    IdleTimeoutMs: 60000
    HeartbeatMs: 0
    ConnectTimeoutMs: 60000
    myIP: ****
    myPort: ****
    connect successful.
    initialStatus: 220
    initialResponse: ****
    converting to secure connection...
    handshakeMessageType: ServerHello
    handshakeMessageLen: 0x46
    processHandshakeMessage:
      MessageType: ServerHello
      Processing ServerHello...
      ServerHello:
        MajorVersion: 3
        MinorVersion: 1
        SessionIdLen: 32
        CipherSuite: RSA_WITH_3DES_EDE_CBC_SHA
        CipherSuite: 00,0a
        CompressionMethod: 0
        Queueing ServerHello message.
        ServerHello is OK.
    handshakeMessageType: Certificate
    handshakeMessageLen: 0x9b1
    processHandshakeMessage:
      MessageType: Certificate
      ProcessCertificates:
        Certificate:
          derSize: 1288
          certSubjectCN: 
          certSerial: ****
          certIssuerCN: ****
        Certificate:
          derSize: 1184
          certSubjectCN: ****
          certSerial: ****
          certIssuerCN: 
        NumCertificates: 2
        Queueing Certificates message...
    handshakeMessageType: ServerHelloDone
    handshakeMessageLen: 0x0
    processHandshakeMessage:
      MessageType: ServerHelloDone
      Queueing HelloDone message.
    HandshakeQueue:
      MessageType: ServerHello
      MessageType: Certificate
      MessageType: ServerHelloDone
    Dequeued ServerHello message.
    Dequeued Certificate message.
    DequeuedMessageType: ServerHelloDone
    OK to ServerHelloDone!
    No client certificate required by the server.
    Encrypted pre-master secret with server certificate RSA public key is OK.
    Sending ClientKeyExchange...
    Sent ClientKeyExchange message.
    Sending ChangeCipherSpec...
    Sent ChangeCipherSpec message.
    Derived keys.
    Installed new outgoing security params.
    Sending FINISHED message..
    algorithm: des
    keyLength: 192
    Sent FINISHED message..
    numBytesRequested: 5
    Connection closed by server.
    Failed to read beginning of SSL/TLS record.
    Failed to read incoming handshake messages. (3)
    Client handshake failed.
    Failed to convert channel to SSL/TLS
    Failed to connect to FTP server.

FTP MLST command?

Question:

A quickie question about the FTP2 control. I have some clients with strange
FTP servers that return the directory listings in formats that no control
seems to be able to handle (although I have not tried yours!). However, it
is next to impossible to test, since I do not have access to their server.
For them, we use the MLST command, so they return plain filenames (since this
is universally supported, while the full listings vary by server). How do I
do this with FTP2?

Answer:

The Chilkat FTP2 component automatically detects at connect-time whether the FTP server supports MLST. If so, then MLST is automatically used internally. If the server does not support MSLT, then Chilkat FTP2 is already capable of parsing FTP directory listings from virtually every variant of FTP server, including MVS (old mainframes), AS/400’s, OpenVMS, Unix variants, Windows, and many others. In summary: You shouldn’t need to worry about what the FTP server is sending for directory listings. Chilkat FTP2 handles it all internally..

Using Chilkat in Managed C++

The Chilkat VC++ static libraries are for unmanaged C++ applications. A Managed C++ application (using Microsoft’s Managed Extensions for C++) runs within the .NET Framework and therefore must use the Chilkat .NET assembly.

The Chilkat C++ online reference documentation and online examples are for unmanaged C++ applications. For Managed C++, the best choice is to read the C# online documentation and C# online examples (at example-code.com). Managed C++ syntax is closer to C# syntax than unmanaged C++ syntax.

To see the differences in syntax, here are some sample code fragments in unmanaged C++, Managed C++, and C#.

Unmanaged C++

#include <CkFtp2.h>

void FtpExample(void)
    {
    CkFtp2 ftp;

    //  Any string unlocks the component for the 1st 30-days.
    bool success = ftp.UnlockComponent("Anything for 30-day trial");

    ftp.put_Hostname("ftp.example-code.com");
    ftp.put_Username("myLogin");
    ftp.put_Password("myPassword");

    success = ftp.Connect();

 ...

Managed C++

    Chilkat::Ftp2 ftp;
    ftp.UnlockComponent("30-day trial");

    ftp.Hostname = "www.example-code.com";
    ftp.Username = "myLogin";
    ftp.Password = "myPassword";

    bool success = ftp.Connect();

    ....

C#

Chilkat.Ftp2 ftp = new Chilkat.Ftp2();

bool success = ftp.UnlockComponent("Anything for 30-day trial");

ftp.Hostname = "ftp.example-code.com";
ftp.Username = "myLogin";
ftp.Password = "myPassword";

success = ftp.Connect();

...

Upload from ASP code to FTP Server

I get the following support problem about once per week from ASP developers:

The ASP developer wants to upload a file from the client computer where the browser is running, to an FTP server.  He writes ASP code to do the FTP upload, but cannot understand why the file is not found.  The thing the ASP developer doesn’t realize is that his ASP code runs on the web server, not on the client computer where the browser is running.

When I detect this misunderstanding, I’ll be pointing you to this blog post.  Here’s a summary of what you should know:

  1. Your browser, such as Internet Explorer, is running on computer “A”.
  2. The browser communicates with a web server running on computer “B”.
  3. Your ASP code runs within the web server’s worker process on computer “B”.
  4. Your FTP server runs on computer “C”.
  5. Your ASP code (running on computer “B”) is trying to upload a file to the FTP server on computer “C”.  Therefore, it is trying to transfer a file from “B” to “C”.
  6. If you want to upload a file from computer “A” to the FTP server (computer “C”), you need to first do an HTTP upload via HTML using a Form with “<input type=”file” …”.  This uploads from the computer where the browser runs to the web server. Your ASP code then uploads the code from the web server to the FTP server.

Determining FTP2 Connection Settings

There are many FTP2 component properties that affect how data connections are established between the FTP client (Chilkat FTP2) and the FTP server. Finding a workable combination of property settings for a given client/server situation can be difficult.  This blog post can hopefully provide some guidance.

Before beginning, it is crucial to understand one basic thing about the FTP protocol: The control connection (typically port 21 or 990) is used for sending commands and getting responses. File uploads/downloads and directory listings are NOT transferred over the control channel. A separate data connection is established for each transfer. One side is responsible for choosing a port number and accepting the data connection, the other side initiates the connection. The direction of the data connection establishment is controlled by the Passive property setting. Passive=true uses passive mode. If Passive=false, then “Active” mode (also known as “port” mode) is used.

Active Mode: The FTP client chooses a port number and sends a “PORT” command to the FTP server. The FTP client then listens at the chosen port and the FTP server issues a connect request to establish the connection. The data connection is outgoing from the FTP server, and incoming to the FTP client.

Passive Mode:
The FTP client sends a PASV command to the FTP server. The FTP server chooses a port number and sends it in the PASV response. The FTP server then listens at that port for the incoming connect request from the FTP client. The data connection is incoming to the FTP server, and outgoing from the FTP client.

The data connection establishment can be blocked at either side (client or server) by many things:  firewalls, TCP/IP port filtering, anti-virus, NAT routers causing problems, etc.

If a file upload or download fails with the dreaded “WSAEWOULDBLOCK” message in the LastErrorText, it means that something blocked the data connection.

The first thing to try in resolving the problem is to reverse the value of the Passive property.  If that doesn’t work, try calling the DetermineSettings method to try a collection of approximately 15 different combinations of property settings.  Examples for DetermineSettings can be found at example-code.com.

The DetermineSettings method does not try all combinations of property settings.  It cannot because there are too many potential combinations.

The FTP2 property settings involved in the data connection establishment are:

  • ActivePortRangeEnd
  • ActivePortRangeStart
  • AuthSsl
  • AuthTls
  • ForcePortIpAddress
  • Passive
  • PassiveUseHostAddr
  • Ssl
  • UseEpsv

If you are able to transfer files using other FTP client software, such as FileZilla, then you should examine the settings of that program and duplicate them w/ Chilkat FTP2.  If you are unsure, you can narrow down the possible combinations by setting the known values.  For example, if you know that FileZilla is working in Passive mode, then you may set the Passive property = true.  This reduces the number of possible combinations by 50%.  Here are some guidelines for duplicating the settings of another FTP client, such as FileZilla:

  • You should certainly know whether the mode being used is Passive or Active (non-passive), so set the FTP2’s passive property appropriately.
  • If Active mode is used, check to see if your FTP client is using a port range.  If so, then set the ActivePortRangeStart and ActivePortRangeEnd properties to the same values.  If not, leave these properties unset.
  • If implicit SSL is used (typically port 990) then set the Ssl property = true.  (Implicit SSL and explicit SSL are mutually exclusive.  if Ssl = true, then both AuthSsl and AuthTls should = false)
  • If explicit SSL is used (AUTH TLS or AUTH SSL) then set either AuthTls = true or AuthSsl = true.  Usually it doesn’t matter which because both commands are technically the same.  Some servers require the “AUTH SSL” command whereas others require “AUTH TLS”.  Most servers don’t care and accept either.
  • If Passive mode is used, test with both PassiveUseHostAddr on and off.   Also test with both UseEpsv on and off.  The ForcePortIpAddress only applies to Active mode, so it can be ignored.
  • If Active mode is used, test with ForcePortIpAddress both on and off.  The PassiveUseHostAddr and UseEpsv properties don’t apply when in Active mode.

Still cannot get it to work?  Programs such as anti-virus may have exceptions for some applications.  It could be that these apps were marked as “trusted” at some earlier time whereas your custom application is not trusted by the anti-virus program.

Cannot get anything to work including all FTP clients such as FileZilla, WS FTP, Internet Explorer, etc.?  It probably means that so many barriers exist on both client and server sides (firewalls, port filtering, anti-virus, NAT routers…) that something must be “opened up” in some way to allow FTP to work.