65.9K
CodeProject 正在变化。 阅读更多。
Home

CFTPClient

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.71/5 (18投票s)

2002年11月30日

CPOL

5分钟阅读

viewsIcon

122449

downloadIcon

6044

实现了几个实用 FTP 函数的 MFC 扩展 DLL

  • 下载演示项目 - 118 Kb
  • 下载源代码 - 44.3 KB
  • 引言

    任何使用过WinInet FTP功能的人可能都注意到了许多功能缺失。特别是,我想要一些代码可以:

    • 支持通配符
    • 可以递归查找子目录以进行上传/下载/删除
    • 可以通过一行代码上传/下载多个文件
    • 可以通过一行代码删除多个文件/文件夹
    • 可以通过一行代码获取文件列表
    • 自动显示进度条并允许用户取消传输

    函数

    主类是CFTPClient

    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)

    要使用被动模式连接,请将bPASV设置为TRUEnRetries表示重传次数。nRetryDelay是每次重试之间的延迟。

    void Logoff ()

    断开与服务器的连接。

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

    • sRemoteFiles是要下载的文件。接受通配符的使用。
    • sLocalFolder是目标文件夹。
    • pbAbort是一个布尔指针。它用于中止传输。如果*pbAbort设置为true,则函数将中止当前操作并返回。

    如果bRecursive为true,则所有子文件夹及其内容也将被下载。

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

    • sLocalFiles是要上传的文件。接受通配符的使用。
    • sRemoteFolder是目标文件夹。
    • pbAbort是一个布尔指针。它用于中止传输。如果*pbAbort设置为true,则函数将中止当前操作并返回。

    如果bRecursivetrue,则所有子文件夹及其内容也将被上传。

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

    • sOrgRemoteFiles是要删除的文件。允许使用通配符。
    • pbAbort是一个布尔指针。它用于中止传输。如果*pbAbort设置为true,则函数将中止当前操作并返回。

    如果bRecursivetrue,则子文件夹中的所有文件也将被删除。如果bAbortIfFailsOnce设置为true,则函数将在第一次错误时中止。否则,它将尝试删除其他文件,然后返回。

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

    • sOrgRemoteFolders是要删除的文件夹。允许使用通配符。请注意,文件夹在删除前必须为空。您可以使用DeleteFiles函数删除文件夹中的内容,然后使用DeleteFolders函数删除空文件夹。
    • pbAbort是一个布尔指针。它用于中止传输。如果*pbAbort设置为true,则函数将中止当前操作并返回。

    如果bRecursivetrue,则子文件夹中的所有文件也将被删除。如果bAbortIfFailsOnce设置为true,则函数将在第一次错误时中止。否则,它将尝试删除其他文件,然后返回。

    void CreateMultiFolder (const CString &sRemoteFolder)

    sRemoteFolder是要创建的文件夹。

    如果为了创建sRemoteFolder需要创建多个文件夹,则函数会自动先创建较低级别的目录。例如,假设您要创建文件夹 /html/my_folder1/my_folder2/my_folder3。如果my_folder1不存在,则函数首先创建my_folder1,然后是my_folder2,最后是my_folder3。

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

    将所有文件名放入sFileNameArraybFullPathGiven应设置为false

    异常处理

    以上所有函数都抛出CFTPException。以下是CFTPException

    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: 发生未知错误。详情请参阅sDesc
    • FTP_LoginFailed: 登录服务器失败。详情请参阅sDesc
    • FTP_AlreadyConnected: 对象已有一个活动连接。请先调用Logoff ()关闭连接。
    • FTP_NotConnected: 对象尚未有活动连接。请先调用Login函数。
    • FTP_Local_FileCreateFailed: 无法创建本地文件。详情请参阅sDesc
    • FTP_Local_FileOpenFailed: 无法打开指定的本地文件。详情请参阅sDesc
    • FTP_Local_UnknownFileError: 发生未知文件错误。详情请参阅sDesc
    • FTP_Remote_SetCurDirFailed: 设置当前FTP目录失败。目录可能不存在或您可能没有权限访问该目录。详情请参阅sDesc
    • FTP_Remote_FileOpenFailed: 无法从远程文件读取。文件可能不存在或您可能没有权限读取该文件。详情请参阅sDesc
    • FTP_Remote_FileWriteFailed: 无法写入远程文件。给定的文件名可能无效,或者您可能没有权限写入该文件。详情请参阅sDesc
    • FTP_CreateFolderFailed: 无法创建文件夹。如果是在远程计算机上,请确保您有创建文件夹的权限。还要确保没有其他文件具有目标文件夹名称。详情请参阅sDesc
    • FTP_DeleteFilesFailed: 无法从服务器删除文件。请确保您有删除文件的权限。详情请参阅sDesc
    • FTP_DeleteFoldersFailed: 无法从服务器删除文件夹。请确保文件夹为空且您有删除文件夹的权限。详情请参阅sDesc
    • FTP_DeleteRootFolderNotAllowed: 不允许删除根文件夹!
    • FTP_InvalidLocalFileName: 给定的文件名无效。详情请参阅sDesc
    • FTP_InvalidRemoteFileName: 给定的文件名无效。详情请参阅sDesc
    • FTP_UserAborted: 用户按下了取消按钮,因此传输被中止。

    用法

    为了使用这些类,您应该

    • 包含 FTPClient.h
    • StdAfx.h 中,包含 <afxinet.h> 以支持MFC Internet。
    • WinInet.lib 添加到链接器选项中的对象/库模块部分。
    • FTPClient.dll 复制到您的可执行文件文件夹中。

    示例

    将一些文件上传到服务器

    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);
    }
    

    从服务器下载文件

    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);
    }
    

    删除所有文件和文件夹

    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);
    }
    

    一个演示程序

    演示程序使用 FTPClient.dll 并实现了一个非常原始的FTP程序。

    谢谢

    • 感谢 Pablo van der Meer 的 FTPWanderer。
    • 感谢 Antonio Tejada Lacaci 的 CFileInfoArray 类。
    • 感谢 The Code Project 为我们所有人提供了一个可用的论坛。

    您应该记住的一些要点

    • 我尚未对这些类进行广泛测试。代码中可能存在一些错误。
    © . All rights reserved.