函数功能:VS2010 —— MFC —— 基于对话框 —— 输入ftp服务器数据、本地下载路径 —— 连接后显示ftp服务器文件情况在列表控件上,有操作功能
从ftp服务器下载指定文件或文件夹到指定的本地路径,保存需要下载的文件大小 ,然后计算本地下载文件大小,比对下载完成度 ,有错误提示。
断点续传功能在第二种方法才有。
使用到的头文件:
#include "stdafx.h" #include "ftpDL.h" #include "ftpDLDlg.h" #include "afxdialogex.h" #include "afxinet.h" #include "afxwin.h" #include <vector> #include "TipDlg.h" //这个是建立的一个新的对话框,主要在双击的时候弹出选择
教程在此:http://www.jizhuomi.com/software/160.html
全局变量定义:
vector <CString> m_string; //创建Vector保存目录 vector <CString> m_dotstring; //保存文件 vector <CString> V_counterpart; //进入下一层按钮时创建当前层副本,记录列表项的数据 CString m_ftppath; //函数需要的输入路径,及搜索当前路径的文件以及目录 vector <CString> V_ftppath; //副本保存路径,显示下一层时用m_ftppath加上**,返回上层时减去** int n; //记录当前显示的层数,根目录为0层, int ig = 0 ; //控制一下创建目录选择哪个 int dir[20]; //创建一个可以保存20个数的数组来保存目录存储时每一层有多少个文件和目录,现在可以存储10层目录,控制这个数组大小可以控制目录的层数 int size[20]; //存储每层多少目录,20表示可以存储20层目录的数据,即每层目录内的文件数量保存在一个数组元素中 LONGLONG m_dirsize = 0; //保存文件的大小 LONGLONG m_fdirsize = 0; //保存ftp要下载的文件或文件夹大小
int nDownloaded; //断点续传的控制
对话框部分的变量输入:(有一项控件是作为重新绘制使用的,如果不需要只需要弄好输入变量的)
DDX_Control(pDX, IDC_localpt_STATIC, m_localpathpos); DDX_Text(pDX, IDC_localpath_EDIT1, m_localpath); DDX_Control(pDX, IDC_localpath_EDIT1, m_editlocalpath); DDX_Control(pDX, IDC_ftppt_STATIC, m_ftppt); DDX_Text(pDX, IDC_ftpadress_EDIT1, m_ftpadress); DDX_Control(pDX,IDC_ftpadress_EDIT1, m_editftpadress); DDX_Control(pDX, IDC_usernm_STATIC, m_usernm); DDX_Text(pDX, IDC_username_EDIT2, m_username); DDX_Control(pDX,IDC_username_EDIT2,m_editusername); DDX_Control(pDX,IDC_passwd_STATIC, m_passwd); DDX_Text(pDX, IDC_password_EDIT3, m_password); DDX_Control(pDX,IDC_password_EDIT3,m_editpassword); DDX_Control(pDX,IDC_pt_STATIC,m_pt); DDX_Text(pDX, IDC_port_EDIT4, m_port); DDX_Control(pDX, IDC_port_EDIT4,m_editport); DDX_Control(pDX,IDC_Fareason_STATIC,m_Fareason); DDX_Text(pDX, IDC_Freason_EDIT5, m_Freason); DDX_Control(pDX,IDC_Freason_EDIT5,m_editFreason); DDX_Control(pDX, IDC_dirshow_LIST1, m_listBox); DDX_Control(pDX, IDC_RIGHTWND,m_rightwnd); DDX_Control(pDX, IDC_connect_BUTTON,m_btconnect); DDX_Control(pDX, IDC_shownextdir_BUTTON,m_btshownextdir); DDX_Control(pDX, IDC_Return_BUTTON,m_btreturn); DDX_Control(pDX, IDC_download_BUTTON,m_btdownload); DDX_Control(pDX, IDCANCEL, m_btcancel);
连接ftp服务器,显示目录在list控件中:
BOOL FtpList(CString &ftppath,CString ftpaddress,CString username,CString &Freason,CString password,int port) //定义ftp目录遍历函数 { CInternetSession sess(_T("List Files Session")); //创建CInternetSession类对象 sess CFtpConnection *pFtpCon=NULL; //创建cftpconnection类对象指针* pFtpCon 为默认值 try { pFtpCon=sess.GetFtpConnection(ftpaddress,username,password,port); //调用GetFtpConnection连接FTP服务器 if(pFtpCon==NULL) { Freason = "connection is false"; return FALSE; } CFtpFileFind ftpDirFinder (pFtpCon); //创建CFtpFileFind类对象ftpDirFinder,"()"内为格式中要求填写的cftpconnection类对象指针 CStringArray m_dir1; //定义一个数组保存目录,一个保存文件 CStringArray m_dir2; BOOL bWorking = ftpDirFinder.FindFile(ftppath); while (bWorking) //循环进行目录调用,保存FTP第一层文件或者文件夹在数组中 { bWorking=ftpDirFinder.FindNextFile(); //循环条件:如果bWork为找不到下一个文件了,循环跳出 if(ftpDirFinder.IsDots()) //这一段为跳过"."和"..“文件,不跳过会无线重复。 { continue; } if(ftpDirFinder.IsDirectory()) { m_dir1.Add( ftpDirFinder.GetFileName()); //如果是目录的话,就保存在数组1 //只需要一层,不用递归,如果用递归,则遍历多层。 } else //找到的不是目录(即文件),保存在数组2 { m_dir2.Add( ftpDirFinder.GetFileName()); //文件保存在数组2中 } } ftpDirFinder.Close(); //关闭ftp连接,开始显示数组中每一项目录 for (int i=0;i<m_dir1.GetSize();i++) //通过循环保存每一项目录或者文件 { m_string.push_back(m_dir1.GetAt(i)); //目录保存在m_string中 } for (int j=0;j<m_dir2.GetSize();j++) { m_dotstring.push_back(m_dir2.GetAt(j)); //文件保存在m_dotstring中 } } catch(CInternetException* pEx) { TCHAR sz[1024]; pEx->GetErrorMessage(sz, 1024); Freason = sz; printf("%s",sz); pEx->Delete(); } if (pFtpCon != NULL) { pFtpCon->Close(); delete pFtpCon; pFtpCon = NULL; } return TRUE; }
下载部分主程序:
下载程序使用到3个另外的自定义函数,一个为检测目录是否存在,另一个是创建多级目录,此2个函数来自csdn的博客,还一个是文件大小比对的自写函数
检测函数:
BOOL FolderExists(CString s) { DWORD attr; attr = GetFileAttributes(s); return (attr != (DWORD)(-1) ) && ( attr & FILE_ATTRIBUTE_DIRECTORY); }
创建目录函数:
BOOL CreateMuliteDirectory(CString P) { int len=P.GetLength(); if ( len <2 ) return false; if('/'==P[len-1]) { P=P.Left(len-1); len=P.GetLength(); } if ( len <=0 ) return false; if (len <=3) { if (FolderExists(P)) return true; else return false; } if (FolderExists(P)) return true; CString Parent; Parent=P.Left(P.ReverseFind('/') ); if(Parent.GetLength()<=0) return false; BOOL Ret=CreateMuliteDirectory(Parent); if(Ret) { SECURITY_ATTRIBUTES sa; sa.nLength=sizeof(SECURITY_ATTRIBUTES); sa.lpSecurityDescriptor=NULL; sa.bInheritHandle=0; Ret=(CreateDirectory(P,&sa)==TRUE); return Ret; } else return FALSE; }
int LocalFileCompa(CString folderpath,LONGLONG netfilesize) //下载文档是文件夹的时候 { int index = folderpath.ReverseFind('/'); if(index == -1) { return FALSE; } CFileFind finder; CString str_path(folderpath); str_path += _T("\\*.*"); vector <LONGLONG> V_nsize; BOOL bWorking = finder.FindFile(folderpath); while (bWorking) { bWorking = finder.FindNextFile(); if (finder.IsDots()) { continue; } else if(finder.IsDirectory()) { LocalFileCompa(finder.GetFilePath(),netfilesize); } else { LONGLONG m_filesize; m_filesize = finder.GetLength(); V_nsize.push_back(m_filesize); } } LONGLONG m_sumsize = 0; for(int i=0;i<V_nsize.size();i++) { m_sumsize += V_nsize[i]; } V_nsize.clear(); LONGLONG comresult; comresult = netfilesize / m_dirsize * 100; CString str; str.Format(_T("%d"),comresult); str = "%"+str; AfxMessageBox(_T("下载程度为")+str); return TRUE; }
以下为下载文件或者文件夹程序:
有两种做法,第一种,使用类cftpconnection::Getfile 函数进行下载:
使用到的类有:
cinternetsession 、 cftpconnection 、 cftpfilefind 、 CInternetFile 、 vector类
可以根据msdn上的例子进行ftp连接和操作,链接:https://msdn.microsoft.com/zh-cn/library/hf9x9wb4.aspx
下载程序代码如下:
BOOL DownloadFromFTP(CString remotepath,CString localpath,CString ftpaddr,CString username,CString &falreason,CString password,int port)
//定义布尔函数DownloadFromFTP { int index = remotepath.ReverseFind('/'); //定义索引本index表示找到与remotepath中最后一个'/'时的值 if (index == -1) { falreason = "'/' can't found"; return FALSE; //表示没有找到 } CString remotefile = remotepath.Mid(index+1,remotepath.GetLength()); //返回'/'后的字符 CInternetSession sess(_T("Download Files Session")); //创建class sess CFtpConnection* pFtpCon = NULL; //创建class pFtpCon为默认值 BOOL b = 0; CInternetFile *fTargFile; //计算文件大小时的指针,以下为一些保存的数据定义 vector <LONGLONG> V_nsize;
int outfs; CString FileSize; try { pFtpCon = sess.GetFtpConnection(ftpaddr,username,password,port); //调用GetFtpConnection连接FTP服务器 if (pFtpCon == NULL) //如果连接失败 { falreason = "connection is false"; return FALSE; //连接失败时的返回结果 } CFtpFileFind ftpFinder(pFtpCon); //定义CFtpFileFind对象 BOOL bWorking = ftpFinder.FindFile(remotepath); // 在FTP上查找remotepath(findfile为文件搜索函数,这里应该是查找FTP上有无此路径) if (bWorking != TRUE) //如果在FTP服务器上没有找到remotepath { falreason = remotepath+ "can't found"; return FALSE; //没找到路径时的返回结果 } CString remotepath1; /*此处为路径处理,思路为先把remotepath当成文件进行下载,如果失败则当初目录下载*/ if(index == 0 | ig == 0) //如果remotepath直接是文件路径(这里是根目录)那么直接下载,//ig,n都是用来表示当前进入了目录的哪一层 { remotepath1 = remotepath.Left(index); } else { index = remotepath.GetLength() - index; remotepath1=remotepath.Right(index); } if(!FolderExists(localpath+remotepath1)) { CreateMuliteDirectory(localpath+remotepath1); //如果最后一个'/'后面还有文件名,那么此程序会创一个名为此文件名的文件夹 } b=pFtpCon->GetFile(remotepath, localpath+remotepath1+'/'+remotefile ,TRUE, FILE_ATTRIBUTE_NORMAL, FTP_TRANSFER_TYPE_BINARY, 1); //GetFile第三项为ture,使得如果目标目录存在此名称的文件,则下载失败返回0导致后面的判断错误 //要问一下是否提示,是否要改为false if ( !b) { while(bWorking) //此循环为下载目录文件的循环 { bWorking = ftpFinder.FindNextFile(); if (ftpFinder.IsDots()) //如果找到的是"."(表示返回顶级目录)或者".."(表示返回上一级目录) { TRACE("%s\n",ftpFinder.GetFileName()); ig --; continue; } else if(ftpFinder.IsDirectory()) //如果找到的是文件夹,递归调用DownloadFromFTP() { TRACE("%s\n",ftpFinder.GetFileName()); ig ++ ; DownloadFromFTP(remotepath+'/'+ftpFinder.GetFileName(),localpath+'/'+remotefile,ftpaddr,username,falreason,password, port); } else //如果找到的是文件,直接下载 { TRACE("%s\n",ftpFinder.GetFileName()); CString remotepath2; remotepath2 += ftpFinder.GetFileName(); int index1 = remotepath.ReverseFind('/'); if (index1==-1) { return false; } index1 = remotepath.GetLength() - index1 ; remotepath2 = remotepath.Right(index1); if(!FolderExists(localpath+remotepath2)) { CreateMuliteDirectory(localpath+remotepath2); } BOOL c; c=pFtpCon->GetFile(remotepath+'/'+ftpFinder.GetFileName(), localpath+remotepath2+'/'+ftpFinder.GetFileName(),TRUE, FILE_ATTRIBUTE_NORMAL, FTP_TRANSFER_TYPE_BINARY, 1); remotepath2.Empty();
/* 下载完成后保存大小*/ if(c) { LONGLONG m_filesize = 0; m_filesize = ftpFinder.GetLength(); //这里使用 cstring保存的时候要考虑cstringa和w的不同 V_nsize.push_back(m_filesize); } } }
/*计算文件夹中文件大小之和*/ LONGLONG m_sumsize = 0; for(int i=0;i<V_nsize.size();i++) { m_sumsize += V_nsize[i]; } m_dirsize += m_sumsize; //要下载的文件大小之和 CString aa =_T(""); m_sumsize = m_dirsize; aa.Format( _T("%d"),m_sumsize ); AfxMessageBox(aa); V_nsize.clear(); } else //要下载路径直接代表的是文件的情况 { ij =1; fTargFile = pFtpCon->OpenFile(remotepath,GENERIC_READ,FTP_TRANSFER_TYPE_BINARY,1 ); __int64 filesize2 = fTargFile->GetLength(); CString aa =_T(""); m_dirsize = filesize2; //储存好了ftp文件大小 aa.Format( _T("%d"),filesize2 ); AfxMessageBox(aa); fTargFile->Close(); CFile *pFile = NULL; pFile = new CFile(localpath+remotepath1+'/'+remotefile,CFile::modeRead | CFile::shareDenyNone); LONGLONG dwLength = pFile->GetLength(); if(m_dirsize == 0 && dwLength == 0) { AfxMessageBox(_T("下载文件为空文件")); } else { LONGLONG comresult; comresult = m_dirsize / dwLength * 100; //空文件时内存泄露,加了判断后没问题了 CString str; str.Format(_T("%d"),comresult); str = "%"+str; AfxMessageBox(_T("下载程度为")+str); } } } catch (CInternetException* pEx) { TCHAR sz[1024]; pEx->GetErrorMessage(sz, 1024); falreason = sz; printf("%s",sz); pEx->Delete(); } if (pFtpCon != NULL) { pFtpCon->Close(); delete pFtpCon; pFtpCon = NULL; } return TRUE; }
第二种:使用读写函数,可以直接在下载的时候就保存文件大小,故不需要使用自写的那个LocalFileCompa函数
BOOL DownloadFromFTP(CString remotepath,CString localpath,CString ftpaddr,CString username,CString &falreason,CString password,int port) //定义布尔函数DownloadFromFTP { int index = remotepath.ReverseFind('/'); //定义索引本index表示找到与remotepath中最后一个'/'时的 if (index == -1) { falreason = "'/' can't found"; return FALSE; //表示没有找到 } CString remotefile = remotepath.Mid(index+1,remotepath.GetLength()); //返回'/'后的字符 CInternetSession sess(_T("Download Files Session")); //创建class sess CFtpConnection* pFtpCon = NULL; //创建class pFtpCon为默认值 BOOL b = 0; CInternetFile *fTargFile; vector <LONGLONG> V_nsize; vector <LONGLONG> V_fsize; CString FileSize; //以下加入断点续传的变量定义 unsigned char filebuf[512]; LONGLONG outfs; CString KBin,Perc; try { pFtpCon = sess.GetFtpConnection(ftpaddr,username,password,port); //调用GetFtpConnection连接FTP服务器 if (pFtpCon == NULL) //如果连接失败 { falreason = "connection is false"; return FALSE; //连接失败时的返回结果 } CFtpFileFind ftpFinder(pFtpCon); //定义CFtpFileFind对象 CString str_path(remotepath); str_path += (_T("\\*.*")); //意思是当前目录下以“任意文件名,任意扩展名”命名的文件 BOOL bWorking = ftpFinder.FindFile(str_path); // 在FTP上查找remotepath(findfile为文件搜索函数,这里应该是查找FTP上有无此路径) if (bWorking != TRUE) //如果在FTP服务器上没有找到remotepath { falreason = remotepath+ "can't found"; return FALSE; //没找到路径时的返回结果 } while(bWorking) //此循环为下载目录文件的循环 { bWorking = ftpFinder.FindNextFile(); if (ftpFinder.IsDots()) //如果找到的是"."(表示返回顶级目录)或者".."(表示返回上一级目录) { TRACE("%s\n",ftpFinder.GetFileName()); ig --; continue; } else if(ftpFinder.IsDirectory()) //如果找到的是文件夹,递归调用DownloadFromFTP() { TRACE("%s\n",ftpFinder.GetFileName()); ig ++ ; DownloadFromFTP(remotepath+'/'+ftpFinder.GetFileName(),localpath+'/'+remotefile,ftpaddr,username,falreason,password, port); } else //如果找到的是文件,直接下载 /223.jpg /220/223.jpg /521/522/223/1.jpg /220 4种情况 { CString openpath ; //这种遍历的改写会导致判断文件与文件夹出错 CString remotepath2; //本地目录创建路径 CString openlocpath; //本地将要写的文件路径 /*以下为路径的拼接,可在调试的时候细看*/ if(remotefile == ftpFinder.GetFileName())//此判断主要用于/223.jpg和/220的区别 { openpath = remotepath; int index1 = openpath.ReverseFind('/'); if (index1==-1) { return false; } else { remotepath2 = openpath.Left(index); openlocpath = localpath + remotepath; } } else if(ig == 0) //根目录文件情况 { openpath = remotepath + '/'+ ftpFinder.GetFileName(); remotepath2 = remotepath; openlocpath = localpath + openpath; } else { openpath = remotepath + '/' + ftpFinder.GetFileName(); remotepath2 = '/'+ remotefile ; openlocpath = localpath + '/'+remotefile+'/'+ftpFinder.GetFileName(); } LONGLONG filesize = ftpFinder.GetLength(); //计算要下载的ftp文件大小 outfs = filesize / 1024; if(filesize == 0) //此处的文件计算改为网络连接 { falreason = "文件大小为0"; return FALSE; } V_fsize.push_back(outfs); FileSize.Format("%d",outfs); fTargFile = pFtpCon->OpenFile(openpath,GENERIC_READ,FTP_TRANSFER_TYPE_BINARY,1 );//getlength必须放在openfile之前才可行 /* 添加openfile错误时的处理代码 */ nDownloaded = 1; if(FolderExists(localpath+remotepath2) == FALSE) //调用函数创建目录 { CreateMuliteDirectory(localpath+remotepath2); } CFile fDestFile; BOOL k; k = fDestFile.Open(openlocpath,CFile::modeCreate | CFile::modeWrite | CFile::typeBinary); //打开目标必须是文件,不然后面的读和写都会错误 if(k == 0) { return FALSE; } LONGLONG byteswrite = 0 ; //保存写入大小 LONGLONG pos = 0 ; //保存已写入数据 LONGLONG nperc, kbrecv;
//百分比 ,已收到数据 ,此百分比只表示当前下载的文件,如果是文件夹,那么会分别显示每一项文件下载的百分比 //与之类似,文件夹时会显示每一项文件的大小 while(byteswrite = fTargFile->Read(filebuf,512)) { pos = pos + byteswrite; fDestFile.Write(filebuf, byteswrite); //..上面的open问题,,改成功 nperc = pos * 100 / filesize; kbrecv = pos / 1024; Perc.Format("%d",nperc); // 格式化进度百分比 KBin.Format("%d",kbrecv); // 格式化已下载数据大小(KB) //AfxMessageBox(Perc); // AfxMessageBox(KBin); } // AfxMessageBox(Perc); // AfxMessageBox(KBin); V_nsize.push_back(kbrecv); fDestFile.Close(); TRACE("%s\n",ftpFinder.GetFileName()); } } LONGLONG m_sumsize = 0; LONGLONG m_fsumsize = 0 ; for(int i=0;i<V_nsize.size();i++) { m_sumsize += V_nsize[i]; } for (int j=0;j<V_fsize.size();j++) { m_fsumsize += V_fsize[j]; } m_dirsize += m_sumsize ; m_fdirsize += m_fsumsize; V_nsize.clear(); V_fsize.clear(); } catch (CInternetException* pEx) { TCHAR sz[1024]; pEx->GetErrorMessage(sz, 1024); falreason = sz; printf("%s",sz); pEx->Delete(); } if (pFtpCon != NULL) { pFtpCon->Close(); delete pFtpCon; pFtpCon = NULL; } return TRUE; }
按钮函数、控件函数 放在下面
void CobjplayerDlg::OnBnClickedconnectButton() { // TODO: Add your control notification handler code here m_string.clear(); m_dotstring.clear(); m_ftppath=(_T("")); m_listBox.ResetContent(); V_counterpart.clear(); n=0; UpdateData(TRUE); FtpList(m_ftppath,(m_ftpadress),(m_username),m_Freason,(m_password),m_port); UpdateData(FALSE); size[n]=m_string.size(); for(unsigned int i=0;i<m_string.size();i++) //显示根目录 0层 { m_listBox.AddString(m_string.at(i)); } if (m_dotstring.size()!=0) { for(unsigned int j=0;j<m_dotstring.size();j++) { m_listBox.AddString(m_dotstring.at(j)); } } } void CobjplayerDlg::OnBnClickedshownextdirButton() { // TODO: Add your control notification handler code here CString n_ftppath; int NcurSel; NcurSel = m_listBox.GetCurSel(); if(m_listBox.GetCount()!=0) //判断是否为空目录,果然为空目录就不执行循环 { if(NcurSel!=-1) //加一个判断,如果未选择列表项则不执行程序并弹出提示框, 未选择时不为1 { if(NcurSel<size[n]) //加一个判断,如果是文件则报错,不执行下面创建副本以及进入下一层目录操作 { if(n+1) //按下显示下一层按钮时创建副本存储当前层数据 { vector <CString> V_n; //创建临时副本V_n CString strText; int numlist; numlist= m_listBox.GetCount(); //当前列表项数量 for(int k=0;k<numlist;k++) { m_listBox.GetText(k,strText); V_n.push_back(strText); //把当前的列表信息保存在当临时副本,数据数量为numlist } for(int l=0;l<numlist;l++) { V_counterpart.push_back(V_n[l]) ; //当前副本信息转移到公共副本 } dir[n]=numlist; //当前目录包含文件数,记录此层存放在公共副本的数据数dir【0】=4 dir【1】=3 //第0层为"" 第一层为/521 numlist=m_listBox.GetCurSel(); m_listBox.GetText(numlist,strText); V_ftppath.push_back("/"+strText); V_n.clear(); //清除临时副本 n++; //当前层数 } m_string.clear(); //此处开始为进入下一层目录的代码 m_dotstring.clear(); m_listBox.GetText(NcurSel, n_ftppath); m_ftppath=m_ftppath+L"/"+n_ftppath; //"/520" m_listBox.ResetContent(); UpdateData(TRUE); FtpList(m_ftppath,(m_ftpadress),(m_username),m_Freason,(m_password),m_port); UpdateData(FALSE); size[n]=m_string.size(); for(unsigned int i=0;i<m_string.size();i++) { m_listBox.AddString(m_string.at(i)); } if (m_dotstring.size()!=0) { for(unsigned int j=0;j<m_dotstring.size();j++) { m_listBox.AddString(m_dotstring.at(j)); } } } else { INT_PTR nRes; // 用于保存DoModal函数的返回值 CTipDlg tipDlg; // 构造对话框类CTipDlg的实例 nRes = tipDlg.DoModal(); // 弹出对话框 if (IDCANCEL == nRes) // 判断对话框退出后返回值是否为IDCANCEL,如果是则return,否则继续向下执行 return; m_listBox.GetText(NcurSel, n_ftppath); m_ftppath=m_ftppath+L"/"+n_ftppath; UpdateData(TRUE); DownloadFromFTP(m_ftppath,(m_localpath),(m_ftpadress),(m_username),m_Freason,(m_password),m_port); UpdateData(FALSE); } } else { CString m_false; m_false="请选择列表项"; AfxMessageBox(m_false); } } else { CString n_false; n_false="空目录,无法进入下一层"; AfxMessageBox(n_false); } } void CobjplayerDlg::OnBnClickedReturnButton() { // TODO: Add your control notification handler code here if(n>0) //n现在是2 { m_string.clear(); m_dotstring.clear(); m_listBox.ResetContent(); //先清除当前列表数据 int l=0; for(int j=0;j<n-1;j++) //除了返回层以外的其他数据数量 { l=l+dir[j]; }//需要显示第1层数据,即后面3个数据,V_counterpart[4] [5] [6] dir[0]=4 dir [1]=3 V_counterpart.size()=7 循环为 for(unsigned int i=l;i<V_counterpart.size();i++) //根据N显示哪一个副本 { m_listBox.AddString(V_counterpart.at(i)); //根据条件显示副本中数据 } V_counterpart.resize(l); m_ftppath.TrimRight(V_ftppath[n-1]); V_ftppath.resize(n-1); //在公共副本中清除当前显示数据层以及之后层的数据 dir[n-1]=0; size[n]=0; n--; //返回处理之后层数,逻辑为显示下一层n+1,返回上一层n-1 } else { CString d_false; d_false="已到达顶层"; AfxMessageBox(d_false); } } void CobjplayerDlg::OnBnClickeddownloadButton() { // TODO: Add your control notification handler code here CString n_ftppath; int NcurSel; NcurSel = m_listBox.GetCurSel(); if(m_listBox.GetCount()!=0) //判断是否为空目录,果然为空目录就不执行循环 { if(NcurSel!=-1) //加一个判断,如果未选择列表项则不执行程序并弹出提示框, 未选择时不为1 { m_listBox.GetText(NcurSel, n_ftppath); CString c_remotepath = m_ftppath; CString c_remotepath1 = m_ftppath; UpdateData(TRUE); m_ftppath=c_remotepath+L"/"+n_ftppath; DownloadFromFTP(m_ftppath,(m_localpath),(m_ftpadress),(m_username),m_Freason,(m_password),m_port); if (ij == 0) { LocalFileCompa(m_localpath+m_ftppath,m_dirsize); } m_ftppath = c_remotepath; UpdateData(FALSE); } else { CString m_false; m_false="请选择列表项"; AfxMessageBox(m_false); } } else { CString n_false; n_false="空目录,无法下载"; AfxMessageBox(n_false); } } void CobjplayerDlg::OnDblclkDirshowList1() { // TODO: Add your control notification handler code here CString n_ftppath; int NcurSel; NcurSel = m_listBox.GetCurSel(); if(m_listBox.GetCount()!=0) //判断是否为空目录,果然为空目录就不执行循环 { if(NcurSel!=-1) //加一个判断,如果未选择列表项则不执行程序并弹出提示框, 未选择时不为1 { if(NcurSel<size[n]) //加一个判断,如果是文件则报错,不执行下面创建副本以及进入下一层目录操作 { if(n+1) //按下显示下一层按钮时创建副本存储当前层数据 { vector <CString> V_n; //创建临时副本V_n CString strText; int numlist; numlist= m_listBox.GetCount(); //当前列表项数量 for(int k=0;k<numlist;k++) { m_listBox.GetText(k,strText); V_n.push_back(strText); //把当前的列表信息保存在当临时副本,数据数量为numlist } for(int l=0;l<numlist;l++) { V_counterpart.push_back(V_n[l]) ; //当前副本信息转移到公共副本 } dir[n]=numlist; //当前目录包含文件数,记录此层存放在公共副本的数据数dir【0】=4 dir【1】=3 //第0层为"" 第一层为/521 numlist=m_listBox.GetCurSel(); m_listBox.GetText(numlist,strText); V_ftppath.push_back("/"+strText); V_n.clear(); //清除临时副本 n++; //当前层数 } m_string.clear(); //此处开始为进入下一层目录的代码 m_dotstring.clear(); m_listBox.GetText(NcurSel, n_ftppath); m_ftppath=m_ftppath+L"/"+n_ftppath; //"/520" m_listBox.ResetContent(); UpdateData(TRUE); FtpList(m_ftppath,(m_ftpadress),(m_username),m_Freason,(m_password),m_port); UpdateData(FALSE); size[n]=m_string.size(); for(unsigned int i=0;i<m_string.size();i++) { m_listBox.AddString(m_string.at(i)); } if (m_dotstring.size()!=0) { for(unsigned int j=0;j<m_dotstring.size();j++) { m_listBox.AddString(m_dotstring.at(j)); } } } else { INT_PTR nRes; // 用于保存DoModal函数的返回值 CTipDlg tipDlg; // 构造对话框类CTipDlg的实例 nRes = tipDlg.DoModal(); // 弹出对话框 if (IDCANCEL == nRes) // 判断对话框退出后返回值是否为IDCANCEL,如果是则return,否则继续向下执行 return; m_listBox.GetText(NcurSel, n_ftppath); m_ftppath=m_ftppath+L"/"+n_ftppath; UpdateData(TRUE); DownloadFromFTP(m_ftppath,(m_localpath),(m_ftpadress),(m_username),m_Freason,(m_password),m_port); UpdateData(FALSE); } } else { CString m_false; m_false="请选择列表项"; AfxMessageBox(m_false); } } else { CString n_false; n_false="空目录,无法进入下一层"; AfxMessageBox(n_false); } }