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

引言
任何使用过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设置为TRUE。nRetries表示重传次数。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,则函数将中止当前操作并返回。
如果bRecursive为true,则所有子文件夹及其内容也将被上传。
 void DeleteFiles (const CString &sOrgRemoteFiles, bool *pbAbort, bool bRecursive, bool bAbortIfFailsOnce)
- 
    sOrgRemoteFiles是要删除的文件。允许使用通配符。
- 
    pbAbort是一个布尔指针。它用于中止传输。如果*pbAbort设置为true,则函数将中止当前操作并返回。
如果bRecursive为true,则子文件夹中的所有文件也将被删除。如果bAbortIfFailsOnce设置为true,则函数将在第一次错误时中止。否则,它将尝试删除其他文件,然后返回。
void DeleteFolders (const CString &sRemoteFolder, bool *pbAbort, bool bRecursive, bool bAbortIfFailsOnce)
- sOrgRemoteFolders是要删除的文件夹。允许使用通配符。请注意,文件夹在删除前必须为空。您可以使用- DeleteFiles函数删除文件夹中的内容,然后使用- DeleteFolders函数删除空文件夹。
- 
    pbAbort是一个布尔指针。它用于中止传输。如果*pbAbort设置为true,则函数将中止当前操作并返回。
如果bRecursive为true,则子文件夹中的所有文件也将被删除。如果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)
将所有文件名放入sFileNameArray。bFullPathGiven应设置为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 为我们所有人提供了一个可用的论坛。
您应该记住的一些要点
- 我尚未对这些类进行广泛测试。代码中可能存在一些错误。




