Click here to Skip to main content
15,879,490 members
Articles / Desktop Programming / MFC
Article

CFTPClient

Rate me:
Please Sign up or sign in to vote.
4.71/5 (21 votes)
21 Jun 2004CPOL5 min read 120.4K   6K   67   19
An MFC Extension DLL that implements some handy FTP functions
  • Download demo project - 118 Kb
  • Download source - 44.3 Kb
  • Introduction

    Anyone who has used the WinInet FTP functions has probably noticed that many features are lacking. In particular, I wanted some code that:

    • Supports wildcards
    • Can recursively look into the sub directories for upload/download/delete
    • Can upload/download multiple files with a single line of code
    • Can delete multiple files/folders with a single line of code
    • Can get the file listing with a single line of code
    • Automatically shows a progress bar and let's the user cancel the transfer

    Functions

    The main class is the CFTPClient class:

    class AFX_EXT_CLASS CFTPClient  
    {
    protected:
        CInternetSession m_InternetSession;
        CFtpConnection *m_pFtpConnection;
        CString m_sFTPRootFolder;
        void SeperateFilename (const CString &sFullName, CString &sFolder, 
            CString &sFilename, TCHAR cFolderSeperator);
    
    public:
        CFTPClient ();
        ~CFTPClient ();
    
        bool IsInitialized  ();
        void Login  (const CString &sHost, const CString &sUsername, 
            const CString &sPassword, BOOL bPASV = FALSE, int nPort = 21, 
            int nRetries = 1, int nRetryDelay = 10);
        void Logoff ();
    
        void Download   (const CString &sRemoteFiles, 
            const CString &sLocalFolder, 
            bool *pbAbort, bool bRecursive = true, 
            DWORD dwTransferType = FTP_TRANSFER_TYPE_BINARY);
        void Upload (const CString &sLocalFiles, const CString &sRemoteFolder, 
            bool *pbAbort, bool bRecursive = true, 
            DWORD dwTransferType = FTP_TRANSFER_TYPE_BINARY);
    
        void DeleteFiles    (const CString &sOrgRemoteFiles, bool *pbAbort, 
            bool bRecursive, bool bAbortIfFailsOnce);
        void DeleteFolders  (const CString &sRemoteFolder, bool *pbAbort, 
            bool bRecursive, bool bAbortIfFailsOnce);
    
        void CreateMultiFolder  (const CString &sRemoteFolder);
    
        void GetFileList    (const CString &sRemoteFolder, 
            bool bFullPathGiven, 
            CStringArray &sFileNameArray, bool bRecursive, 
            bool bExcludeHidden = false);
    
    private:
        void DeleteRemoteFiles  (bool bDeleteFirs, const CString &sOrgRemote, 
            bool *pbAbort, bool bRecursive, bool bAbortIfFailsOnce);
    
        friend class CFTPDownload;
        friend class CFTPUpload;
    };

    void Login (const CString &sHost, const CString &sUsername, const 
        CString &sPassword, BOOL bPASV = FALSE, int nPort = 21, int nRetries = 1, int 
        nRetryDelay = 10)

    To connect using passive mode, set bPASV to TRUE. nRetires represents the number of retransmissions. nRetryDelay is the delay between each retry attempt.

    void Logoff ()

    Disconnects from the server.

    void Download (const CString &sRemoteFiles, const CString &sLocalFolder, 
        bool *pbAbort, bool bRecursive = true, DWORD dwTransferType = FTP_TRANSFER_TYPE_BINARY)

    • sRemoteFiles are the files to be downloaded. Usage of wildcard characters are accepted.
    • sLocalFolder is the destination folder.
    • pbAbort is a pointer to a boolean. It is used to abort the transfers. If *pbAbort is set to true, the function aborts the current operation and returns.

    If bRecursive is true, then all the subfolders and their contents will also be downloaded.

    void Upload (const CString &sLocalFiles, const CString &sRemoteFolder,
       bool *pbAbort, bool bRecursive = true, DWORD dwTransferType = FTP_TRANSFER_TYPE_BINARY)
    

    • sLocalFiles are the files to be uploaded. Usage of wildcard characters are accepted.
    • sRemoteFolder is the destination folder.
    • pbAbort is a pointer to a boolean. It is used to abort the transfers. If *pbAbort is set to true, the functions aborts the current operation and returns.

    If bRecursive is true, then all the subfolders and their contents will also be uploaded.

    void DeleteFiles (const CString &sOrgRemoteFiles, bool *pbAbort,
       bool bRecursive, bool bAbortIfFailsOnce)
    

    • sOrgRemoteFiles are the files to be deleted. Usage of wildcard characters are allowed.
    • pbAbort is a pointer to a boolean. It is used to abort the transfers. If *pbAbort is set to true, the function aborts the current operation and returns.

    If bRecursive is true, then all the files in the subfolders will also be deleted. If bAbortIfFailsOnce is set to true, then the function will abort on the first error. Otherwise, it will try to delete the other files and then return.

    void DeleteFolders (const CString &sRemoteFolder, bool *pbAbort, 
        bool bRecursive, bool bAbortIfFailsOnce)

    • sOrgRemoteFolders are the folders to be deleted. Usage of wildcard characters are allowed. Please note that, the folder MUST be empty before the deletion. You can use DeleteFiles function to delete the contents of the folders and then use DeleteFolders function to delete the empty folders.
    • pbAbort is a pointer to a boolean. It is used to abort the transfers. If *pbAbort is set to true, the function aborts the current operation and returns.

    If bRecursive is true, then all the files in the subfolders will also be deleted. If bAbortIfFailsOnce is set to true, then the function will abort on the first error. Otherwise, it will try to delete the other files and then return.

    void CreateMultiFolder (const CString &sRemoteFolder)

    sRemoteFolder is the folder to be created.

    If in order to create sRemoteFolder multiple folders should be created, the function automatically creates the lower level directories first. For example, suppose you want to create a folder /html/my_folder1/my_folder2/my_folder3. If my_folder1 does not exist, then the function first creates my_folder1 and then my_folder2 and lastly my_folder3.

    void GetFileList (const CString &sRemoteFolder, bool bFullPathGiven, 
        CStringArray &sFileNameArray, bool bRecursive, bool bExcludeHidden = false)

    Puts all the filenames into sFileNameArray. bFullPathGiven should be set to false.

    Exception Handling

    All of the functions above throws CFTPException. Here is the CFTPException class:

    class AFX_EXT_CLASS CFTPException : public CException
    {
    public:
        enum FTPError
        {
            FTP_Unknown,
            FTP_LoginFailed,
            FTP_AlreadyConnected,
            FTP_NotConnected,
            FTP_Local_FileCreateFailed,
            FTP_Local_FileOpenFailed,
            FTP_Local_UnknownFileError,
            FTP_Remote_SetCurDirFailed,
            FTP_Remote_FileOpenFailed,
            FTP_Remote_FileWriteFailed,
            FTP_CreateFolderFailed,
            FTP_DeleteFilesFailed,
            FTP_DeleteFoldersFailed,
            FTP_DeleteRootFolderNotAllowed,
            FTP_InvalidLocalFileName,
            FTP_InvalidRemoteFileName,
            FTP_UserAborted
        };
    
        int m_nError;
        CString m_sDesc;
    
        CFTPException (FTPError nError, 
            const CString &sDesc) : CException (TRUE)
        {
            m_nError = nError;
            m_sDesc = sDesc;
        }
    };
    • FTP_Unknown: An unknown error occurred. See sDesc for details.
    • FTP_LoginFailed: Login to the server failed. See sDesc for details.
    • FTP_AlreadyConnected: The object already has an active connection. First call Logoff () to close the connection.
    • FTP_NotConnected: The object has no active connection yet. Call Login function first.
    • FTP_Local_FileCreateFailed: Cannot create the local file. See sDesc for details.
    • FTP_Local_FileOpenFailed: Cannot open the specified local file. See sDesc for details.
    • FTP_Local_UnknownFileError: An unknown file error occurred. See sDesc for details.
    • FTP_Remote_SetCurDirFailed: Setting current FTP directory failed. The directory may not exist or you may not have permissions to access the directory. See sDesc for details.
    • FTP_Remote_FileOpenFailed: Cannot read from the remote file. The file may not exist or you may not have the permissions to read that file. See sDesc for details.
    • FTP_Remote_FileWriteFailed: Cannot write to the remote file. The filename given may be invalid, or you may not have the permissions to write to that file. See sDesc for details.
    • FTP_CreateFolderFailed: Cannot create the folder. If it is on the remote machine, be sure that you have permissions to create a folder. Also be sure that another file does not have the destination folder name. See sDesc for details.
    • FTP_DeleteFilesFailed: Cannot delete files from the server. Be sure that you have the permissions to delete files. See sDesc for details.
    • FTP_DeleteFoldersFailed: Cannot delete folders from the server. Be sure that the folders are empty and you have the permissions to delete folders. See sDesc for details.
    • FTP_DeleteRootFolderNotAllowed: Deletion of root folder is not allowed!
    • FTP_InvalidLocalFileName: The filename given is invalid. See sDesc for details.
    • FTP_InvalidRemoteFileName: The filename given is invalid. See sDesc for details.
    • FTP_UserAborted: User pressed the cancel button and thus the transfer is aborted.

    Usage

    In order to use these classes, you should:

    • Include FTPClient.h.
    • In StdAfx.h, include <afxinet.h> for MFC Internet support.
    • Add WinInet.lib to the Object/Library Modules section in Linker options.
    • Copy FTPClient.dll to your executable's folder.

    Examples

    Upload some files to the server

    try
    {
        bool bAbort = false;
        m_FTPClient.Upload ("c:\\my_web\\*", "public_html/", &bAbort, true);
    }
    catch (CFTPException *pEx) 
    {
        switch (pEx->m_nError)
        {
            // You can check for all exception types here!
        case FTP_NotConnected:
            break;
        }
        CString sDesc = pEx->m_sDesc;
        pEx->Delete ();
        AfxMessageBox (sDesc);
    }

    Download files from the server

    try
    {
        bool bAbort = false;
        m_FTPClient.Download ("public_html/*", "c:\\my_web\\",  &bAbort, true);
    }
    catch (CFTPException *pEx) 
    {
        switch (pEx->m_nError)
        {
            // You can check for all exception types here!
        case FTP_NotConnected:
            break;
        }
        CString sDesc = pEx->m_sDesc;
        pEx->Delete ();
        AfxMessageBox (sDesc);
    }

    Delete all files and folders

    try
    {
        bool bAbort = false;
        // First delete all the files
        m_FTPClient.DeleteFiles ("tmp/*", &bAbort, true, true);
        // Now all the folders are empty. We can safely delete them
        m_FTPClient.DeleteFolders ("tmp/*", &bAbort, true, true);
    }
    catch (CFTPException *pEx) 
    {
        switch (pEx->m_nError)
        {
            // You can check for all exception types here!
        case FTP_NotConnected:
            break;
        }
        CString sDesc = pEx->m_sDesc;
        pEx->Delete ();
        AfxMessageBox (sDesc);
    }

    A Demo Program

    The demo program uses FTPClient.dll and implements a very primitive FTP program.

    Thanks

    • To Pablo van der Meer for FTPWanderer.
    • To Antonio Tejada Lacaci for CFileInfoArray class.
    • To The Code Project, for providing a useable forum for all of us.

    Some points that you should keep in mind

    • I have not tested these classes extensively yet. There may be some bugs in the code.

    License

    This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


    Written By
    Software Developer
    United States United States
    This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

    Comments and Discussions

     
    GeneralMy vote of 5 Pin
    ytfrdfiw31-Oct-12 20:23
    ytfrdfiw31-Oct-12 20:23 
    GeneralVista or Win-7 [modified] Pin
    plattenbomber2-Mar-11 1:51
    plattenbomber2-Mar-11 1:51 
    GeneralOverwriting file(s) during upload and download [modified] Pin
    thelvaci24-Nov-06 10:19
    thelvaci24-Nov-06 10:19 
    GeneralSometimes programs never exit from the FindFile Pin
    WHRIA19-Aug-06 13:17
    WHRIA19-Aug-06 13:17 
    GeneralSecured FTP using SSL Pin
    dchauhan24-Mar-05 22:49
    dchauhan24-Mar-05 22:49 
    GeneralLinker Error 2019 Pin
    elgilou2-May-04 13:30
    elgilou2-May-04 13:30 
    GeneralWindows 98 and CFTPClient HELP ME PLEASE!!!!!!!S.O.S. Pin
    FranciscoDanielSPereira5-Mar-04 2:18
    FranciscoDanielSPereira5-Mar-04 2:18 
    GeneralRe: Windows 98 and CFTPClient HELP ME PLEASE!!!!!!!S.O.S. Pin
    Mustafa Demirhan5-Mar-04 6:12
    Mustafa Demirhan5-Mar-04 6:12 
    GeneralRe: Windows 98 and CFTPClient HELP ME PLEASE!!!!!!!S.O.S. Pin
    FranciscoDanielSPereira6-Mar-04 17:24
    FranciscoDanielSPereira6-Mar-04 17:24 
    Generalssl + tls Pin
    [-andy-]25-Jan-04 4:53
    [-andy-]25-Jan-04 4:53 
    GeneralRe: ssl + tls Pin
    dchauhan24-Mar-05 22:50
    dchauhan24-Mar-05 22:50 
    Generalcannot connect Pin
    YoSilver23-Jan-04 21:12
    YoSilver23-Jan-04 21:12 
    GeneralRe: cannot connect Pin
    YoSilver23-Jan-04 21:22
    YoSilver23-Jan-04 21:22 
    GeneralRe: cannot connect Pin
    Mustafa Demirhan24-Jan-04 7:44
    Mustafa Demirhan24-Jan-04 7:44 
    YoSilver wrote:
    Why on earth you set the timeout to 30 MILLIseconds???

    Sorry, my bad. OMG | :OMG: I thought i set it to 30 seconds, not to 30 milliseconds.

    Mustafa Demirhan
    http://www.macroangel.com

    "What we do in life echoes in eternity" - Gladiator
    It's not that I'm lazy, it's just that I just don't care

    GeneralDownload and Delete multiple files. Pin
    hwjang116-Jan-04 22:40
    hwjang116-Jan-04 22:40 
    GeneralStatusCalback In ftp Pin
    batraAnjali15-Nov-03 0:09
    batraAnjali15-Nov-03 0:09 
    Generalneed help:FTP Pin
    girishnadig29-Aug-03 1:17
    girishnadig29-Aug-03 1:17 
    GeneralRe: need help:FTP Pin
    Mustafa Demirhan29-Aug-03 8:53
    Mustafa Demirhan29-Aug-03 8:53 
    Questionhow to creat multi-subdir at ftpserver? Pin
    stephen(china)3-Aug-03 22:02
    stephen(china)3-Aug-03 22:02 

    General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

    Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.