4.4.3 使用CFtp类编程(www.cppentry.com)
如图4.6所示,用户登录服务器的方式可以是程序默认的匿名登录,同时也可以使用指定账号登录。其响应代码如下:
- void CFTPDlg::OnRadio2()
- {
- this->GetDlgItem(IDC_EDIT3)->EnableWindow
(true); //禁用IDC_EDIT3编辑框 - this->GetDlgItem(IDC_EDIT4)->EnableWindow(true);
- //禁用IDC_EDIT4编辑框
- }
当用户输入服务器IP地址等信息后,单击"连接服务器"按钮,程序根据用户提供的信息对服务器进行连接。该按钮对应的消息响应函数代码如下:
- void CFTPDlg::OnConnect()
- {
- CString str,str1; //定义字符串变量
- int port=0; //定义端口变量
- this->GetDlgItem(IDC_EDIT1)->GetWindowText(str); //获取IP字符串
- this->GetDlgItem(IDC_EDIT2)->GetWindowText(str1); //获取端口号码
- port=(int)atoi(str1); //将端口字符串转换成数字
- if(ftp.FTPConnect(str,port)) //调用CFtp对象的函数进行连接
- {
- this->GetDlgItem(IDC_EDIT5)->SetWindowText("连接成功!"); //通知用户连接状态
- this->GetDlgItem(IDC_Connect)->EnableWindow(false);
- //连接成功后,设置连接按钮为失效状态
- ftp.Send("LIST/r/n"); //发送命令获取文件列表信息
- str=ftp. Recv();//接收数据
- ftp.GetFileStatu(str.GetAt(0)); //获取文件名称
- }}
在客户端启动时,应该能获取到本地默认文件夹下的文件。在VC中,查找文件的API函数主要是FindFirstFile()和FindNextFile()函数。函数原型分别如下:
- //开始查找文件并获得其句柄
- HANDLE FindFirstFile(
- LPCTSTR lpFileName,
- FINDEX_INFO_LEVELS fInfoLevelId,
- LPVOID lpFindFileData,
- FINDEX_SEARCH_OPS fSearchOp,
- LPVOID lpSearchFilter,
- DWORD dwAdditionalFlags
- );
- //从当前位置查找下一个文件
- BOOL FindNextFile(
- HANDLE hFindFile,
- LPWIN32_FIND_DATA lpFindFileData
- );
函数FindFirstFile()可以在指定盘符下查找文件,并将获取到的文件数据保存到缓冲区中,该函数返回文件查找操作的句柄。参数lpFileName表示用户需要查找的文件名。如果该名称中没有包含路径,则程序会在当前目录下进行查找文件,否则在指定路径下查找文件。在文件名中可以使用"*"等通配符代替,如下:
- lpFileName="C:\\windows\\*.*"; //在C:\\windows
\\下查找所有文件 - lpFileName="C:\\windows\\*.txt"; //在目录
C:\\windows\\下查找所有TXT文件 - lpFileName="C:\\windows\\vtk.bin"; //在目录
C:\\windows\\下查找文件vtk.bin - lpFileName="C:\\windows\\*.exe"; //在目录
C:\\windows\\下查找所有EXE文件
函数FindNextFile()可以继续查找其他格式的文件操作。参数hFindFile表示函数FindFirstFile()返回的操作句柄。参数lpFindFileData指向结构体WIN32_FIND_DATA,保存了程序所找到的文件名和文件属性等数据。该函数调用成功返回true,否则,返回false。WIN32_FIND_DATA结构如下:
- typedef struct _WIN32_FIND_DATA {
- DWORD dwFileAttributes; //文件属性
- FILETIME ftCreationTime; //文件创建日期
- FILETIME ftLastAccessTime; //文件最后保存日期
- FILETIME ftLastWriteTime; //文件最后修改日期
- DWORD nFileSizeHigh; //文件长度的高32位
- DWORD nFileSizeLow; //文件长度的低32位
- DWORD dwReserved0; //现在保留
- DWORD dwReserved1; //现在保留
- TCHAR cFileName[MAX-PATH]; //本次查找到的文件名
- TCHAR cAlternateFileName[14]; //文件的短文件名
- } WIN32_FIND_DATA;
注意:参数cAlternateFileName[14]表示文件的短文件名。例如,文件路径为C:\\windows\\ vtk.bin的文件短名称为vtk.bin。
用户在客户端启动时,可以使用上面两个函数进行文件的查找。其代码如下:
- BOOL CFTPDlg::OnInitDialog()
- {
- ... //省略部分代码
- int i=0;
- LVITEM item={0}; //初始化列表结构
- item.mask=LVIF_TEXT;//指定pszText域有效
- WIN32_FIND_DATA filedata={0}; //初
始化结构体WIN32_FIND_DATA - HANDLE filehand; //文件句柄
- filehand=::FindFirstFile("C:\\*",&filedata);
//查找C盘下所有文件 - while(::FindNextFile(filehand, &filedata))
- {
- item.pszText=(LPTSTR) filedata. cFileName; //将文件名称赋给列表项
- this->GetDlgItem(IDC_LIST1)-> InsertColumn(
i,& item); //在列表中插入栏目名称 - i+=1;
- }
- return TRUE;
- }
除了上述获取文件的方式以外,还可以通过用户选择的特定盘符进行获取。其中,响应用户选择的函数是CFTPDlg::OnSelchangeCombo1(),代码如下:
- void CFTPDlg::OnSelchangeCombo1() //组
合框选择消息响应 - {
- CString str; //定义字符串变量
- int i=m_c1.GetCurSel(); //获取
用户单击位置的索引 - m_c1.GetLBText(i,str);//获取索引处的字符
- str+=" * "; //添加通配符"*"
- WIN32_FIND_DATA filedata={0}; //初始
化结构体WIN32_FIND_DATA - HANDLE filehand; //文件句柄
- filehand=::FindFirstFile(str,&filedata); //查
找特定盘下所有文件 - while(::FindNextFile(filehand, &filedata))
- {
- item.pszText=(LPTSTR) filedata. cFileName; //将
文件名称赋给列表项 - this->GetDlgItem(IDC_LIST1)-> insertColumn(i,&
item); //在列表中插入栏目名称 - i+=1;
- } }
m_c1是CComboBox类的对象。通过代码,程序可以获取用户所选择目录下的所有文件并且显示在列表中。用户获取服务器文件名称和获取本地文件名称的实现方法一样,使用CFtp类函数GetFileStatu()获取服务器文件名称,然后设置列表控件的栏目即可,所以这里不再赘述。
在本地文件列表中,用户需要响应右键消息。在右键消息响应函数中获取文件名称,调用CFtp类的函数UpDataFile()上传文件。
- void CFTPDlg::OnRclickList1(NMHDR* pNMHDR, LRESULT* pResult)
- {
- CString str1;
- int i= this->GetDlgItem(IDC_LIST1)->GetCurSel();
//获得单击鼠标位置的索引 - CString str= this->GetDlgItem(IDC_LIST1)->GetText(i);
- //获取索引位置的文件名称
- WIN32_FIND_DATA filedata={0}; //初始
化结构体WIN32_FIND_DATA - HANDLE filehand;
- filehand=::FindFirstFile("C:\\*",&filedata); //查找C盘下所有文件
- while(::FindNextFile(filehand, &filedata))//在文
件中查找与指定文件名称相同的文件 - {
- if(str==(LPTSTR) filedata. cFileName)
- {
- str1+="C:\\"+str; //构造文件完整路径
- ftp. UpdataFile("str");//上传指定文件
- }
- }}
上传函数中,使用列表控件中的函数GetCurSel()获取指定索引,再调用函数GetText()获取文件名称。然后使用函数FindFirstFile()和FindNextFile()查找对应文件,构造完整路径后调用CFtp类函数UpDataFile()上传该文件。
在服务器文件列表中,响应右键消息。其消息响应函数如下:
- void CFTPDlg::OnRclickList2(NMHDR* pNMHDR, LRESULT* pResult)
- {
- int i= this->GetDlgItem(IDC_LIST1)->GetCurSel();
//获得单击鼠标位置的索引 - CString str= this->GetDlgItem(IDC_LIST1)->GetText(i);
- //获取索引位置的文件名称
- WIN32_FIND_DATA filedata={0}; //初始
化结构体WIN32_FIND_DATA - HANDLE filehand;
- filehand=::FindFirstFile("ftp://127.0.0.1/ftp",&filedata);
- //查找服务器下ftp文件夹中内容
- while(::FindNextFile(filehand, &filedata))
- //在文件中查找与指定文件名称相同的文件
- {
- if(str==(LPTSTR) filedata. cFileName)
- {
- str1+=" ftp://127.0.0.1\ftp\"+str; //构
造文件完整路径 - ftp.DownLoadFile(str); //调用CFtp类
的DownLoadFile()函数进行下载 - }
本节主要讲解了自定义类CFtp的使用方法,其用法非常简单。如果用户需要扩展其内容,首先在文件"Ftp.h"中自定义函数或数据。然后在"Ftp.CPP"中写出自定义函数的代码即可。本节中详细代码请参考光盘中4.4.3小节文件夹。