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 为我们所有人提供了一个可用的论坛。
您应该记住的一些要点
- 我尚未对这些类进行广泛测试。代码中可能存在一些错误。