EVC下Ftp遍历下载所有文件夹

 EVC下Ftp遍历下载所有文件夹(原创)

本文讨论在Evc下遍历ftp站点的文件并下载,google了很多天,找到相关资料,但在evc下应用的很少,此文总结方法并应用到evc,以共享。

      ftp站点的访问有很多方法,本文使用InternetOpen,InternetConnect两函数来连接,因在evc环境下并不支持CFtpFileFind类,可用FtpFindFirstFile,InternetFindNextFile来遍历文件夹,用FtpGetFile下载文件,此方法是win API函数,在多种windows开发平台上都可以使用。

      这几个函数的结合在google上可以轻易搜索到,在此介绍下此次开发过程中遇到的问题:

1 关于evc下遍历文件夹的方法

    vc下遍历ftp文件夹的方法很简单,又专门的类CFtpFileFind,通过此类可直接查找文件,但是evc下不支持这个类的使用。在windows遍历文件夹使用FindFirstFile和FindNextFile,此方法可访问本地和局域网的文件夹,如访问:"192.168.1.230//Share",注意此时的文件夹中的斜杠的数量,必须是这种格式的,但此方法无法访问远程的ftp站点,最终找到FtpFindFirstFile,InternetFindNextFile结合的方法,可以使用;

2 使用FtpFindFirstFile,InternetFindNextFile查找的文件夹类型

     ftp站点下的每个文件夹下都有两个文件夹"."和".."存在,"."代表本目录路径,".."代表上一级路径,所以在搜索到文件夹时需做判断排除此文件夹。

3 使用FtpFindFirstFile后无法用InternetFindNextFile继续查找下一个文件或文件夹

     在使用函数InternetOpen(_T("ftp"),INTERNET_OPEN_TYPE_DIRECT,NULL,NULL,0)时注意参数设置,起初我最后一个参数使用了INTERNET_FLAG_ASYNC,MSDN上的解释是Makes only asynchronous requests on handles descended from the handle returned from this function. Only the InternetOpen function uses this flag. 我尚未弄清该参数的具体意义,起初使用是参考其他网友的版本,大家可研究下。还有注意的是第一个参数不能为NULL,否则open出错。

4 使用FtpFindFirstFile查询后,发现文件夹遍历进入后,再搜索时发现FtpFindFirstFile的返回值为0

      在这里要注意的是,在进入下一级文件夹后,必须先调用InternetCloseHandle(hFind)!!!否则结果就像上面描述的那样了,返回0。

      这样使用后,会存在递归调用下载的问题,因为程序逻辑是,如果发现文件夹即递归进入,之前的hFind已经被关闭,这样递归返回后,其余文件无法下载了,所以此处采用的方法是,在递归发现文件夹后把文件夹名保存,下载此目录下的其他文件,全部完毕后,再调用文件夹名递归进入下一级文件夹,这样之前的hFind被关闭后也不存在返回的问题了。

5 自己经验,供大家共享,如有问题,欢迎反馈!

以下是主要代码,经测试通过可以在evc下运行。

头文件:

#include "wininet.h"
#include <afxinet.h>

project settings->link->添加wininet.lib

// 递归创建目录  
void   CreateAllDirectories(CString   strDir)  
{  
 if(strDir.GetLength()!=0)  
 {  
  if(strDir.Right(1)=="//")  
   strDir=strDir.Left(strDir.GetLength()-1);    
  //   目录存在则返回  
  if(GetFileAttributes(strDir)!=-1)    
   return;  
  //   递归创建目录  
  int   nFound   =   strDir.ReverseFind('//');  
  CreateAllDirectories(strDir.Left(nFound));    
  //   实际创建目录  
  CreateDirectory(strDir,NULL);  
 }  

//递归下载
void FtpEnumDirectory(HINTERNET hConnect,CString szSourceDir,CString szSaveDir)
{
 CString   szFileName;
 CStringArray dirs;
 WIN32_FIND_DATA   pData;
 HINTERNET hFind;
 //   Start   enumeration   and   get   file   handle
 if(szSourceDir.GetAt(szSourceDir.GetLength()-1)!='/')
  szSourceDir+="/";
 hFind = FtpFindFirstFile(hConnect, szSourceDir+"*.*", &pData, 0, 0);
 if (!hFind)  
 {
  if(GetLastError() == ERROR_NO_MORE_FILES)    
  {  
  
   InternetCloseHandle(hFind);
  }  
  else  
  {  
   AfxMessageBox(_T("FindFirst failed"));
   InternetCloseHandle(hFind);
   return ;  
  } 
 }
 else
 //do
 {
  szFileName=pData.cFileName;
  if(pData.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY)  
  {
   if((szFileName!=".") && (szFileName != ".."))   //content   is   sub   dir  
   {  
    //递归
    FtpSetCurrentDirectory(hConnect,szSourceDir+szFileName);
    dirs.Add(szFileName);
   }
  }
  else   //download
  {
   CreateAllDirectories(szSaveDir);  
   if(!FtpGetFile(hConnect,szSourceDir+szFileName,szSaveDir+"//"+szFileName,FALSE,FILE_ATTRIBUTE_NORMAL,FTP_TRANSFER_TYPE_ASCII | INTERNET_FLAG_TRANSFER_ASCII | INTERNET_FLAG_RELOAD ,NULL))
   {
    AfxMessageBox(_T("FtpGetFile failed"));
    return;
   }
  }
 }//while(InternetFindNextFile(hFind,&pData));
 do
 {
  if(!InternetFindNextFile(hFind,&pData))
  {
  if(GetLastError() == ERROR_NO_MORE_FILES)    
  {  
   InternetCloseHandle(hFind);
   break;
  }  
  else  
  {  
   AfxMessageBox(_T("FindNext failed"));
   InternetCloseHandle(hFind);
   return;  
  } 
  }
  else
  {
  szFileName=(LPCTSTR) &pData.cFileName;
  //   Entry   is   a   directory,   mark   it   as   such  
  if(pData.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY)  
  {
   if((szFileName!=".") && (szFileName != ".."))   //content   is   sub   dir  
   {  
    //递归
    FtpSetCurrentDirectory(hConnect,szSourceDir+szFileName);
    dirs.Add(szFileName);
   }
  }
  else   //download
  {
   CreateAllDirectories(szSaveDir);  
   if(!FtpGetFile(hConnect,szSourceDir+szFileName,szSaveDir+"//"+szFileName,FALSE,FILE_ATTRIBUTE_NORMAL,FTP_TRANSFER_TYPE_ASCII | INTERNET_FLAG_TRANSFER_ASCII | INTERNET_FLAG_RELOAD ,NULL))
   {
    AfxMessageBox(_T("FtpGetFile failed"));
    return;
   }
  }
  }
 } while(TRUE);

    for(int i=0;i<dirs.GetSize();i++)
 {
  //InternetCloseHandle(hFind);
  szFileName=dirs.GetAt(i);
     FtpEnumDirectory(hConnect,szSourceDir+szFileName,szSaveDir+"//"+szFileName);
 }
 return;
}
//连接ftp
BOOL  FtpDownloadFiles (CString IpAddress,CString szftpDir,CString szSaveDir)  
{  
 HINTERNET hConnect,hHost;  

 hHost=InternetOpen(_T("ftp"),INTERNET_OPEN_TYPE_DIRECT,NULL,NULL,0);
 if(!hHost)
 {
  CString str;
  str.Format(_T("Open Error: %Xh"),GetLastError());
  AfxMessageBox(str);
  return FALSE;
 }
    hConnect=InternetConnect(hHost,IpAddress,INTERNET_DEFAULT_FTP_PORT,NULL,NULL,INTERNET_SERVICE_FTP,0,0);  
    if(!hConnect)
 {
  AfxMessageBox(_T("InternetConnect failed"));
  InternetCloseHandle(hHost);
  return FALSE;
 }
 FtpEnumDirectory(hConnect,szftpDir,szSaveDir);
 InternetCloseHandle(hConnect);
 InternetCloseHandle(hHost);
  return TRUE;  


void CRFtpDownDlg::OnRdown()
{
 // TODO: Add your control notification handler code here
 CString ip=_T("192.168.1.150");
 CString szftpDir=_T("/");
 CString szSaveDir=_T("/ftp");
 if(FtpDownloadFiles(ip,szftpDir,szSaveDir))
  AfxMessageBox(_T("Download Finished!"));
}

附:VC下遍历下载代码,使用CFtpFindFile类(本文参考内容,根据其思路改进,出自csdn论坛,感谢达人!)

#include   <afxinet.h>  
  //2   递归下载文件  
  void   GetTree(CFtpConnection*   objConn,CString   strSour,CString   strDest)  
  {  
  CStringArray   dirList;  
   
  CFtpFileFind   ftpFind(objConn);  
  if(strSour.GetAt(strSour.GetLength()-1)!='/')strSour+="/";  
  BOOL   bContinue   =   ftpFind.FindFile(strSour+"*");  
  if   (!bContinue)  
  {  
  ftpFind.Close();  
  return;  
  }  
  BOOL   bDir   =   FALSE;  
  CString   strFileName,   strFilePath;  
  while   (bContinue)  
  {  
  bContinue   =   ftpFind.FindNextFile();  
  strFileName   =   ftpFind.GetFileName();  
  strFilePath   =   ftpFind.GetFilePath();  
  if   (ftpFind.IsDirectory())  
  {  
  bDir   =   TRUE;  
  dirList.Add(strFileName);  
  }  
  else  
  {  
  //   创建目录  
  ::CreateAllDirectories(strDest);  
  //   执行下载  
  objConn->GetFile(strFilePath,strDest+"//"+strFileName,FALSE);  
  //AfxMessageBox(strFilePath+"->"+strDest+"//"+strFileName);  
  }  
  }  
  ftpFind.Close();  
  int   count=dirList.GetSize();  
  for(int   i=0;i<count;i++)  
  {  
  strFileName   =   dirList.GetAt(i);  
  GetTree(objConn,strSour+strFileName,strDest+"//"+strFileName);  
  }  
  dirList.RemoveAll();  
  }  
  //   3   建立FTP连接  
  void   CFtpDlg::OnButtonDo()    
  {  
  CString   strServerName   =   "192.168.0.199";  
  CString   strUserName   =   "administrator";  
  CString   strPassword   =   "zhrmghg";  
  CString   strSourPath   =   "/";  
  CString   strDestPath   =   "d://abc";  
   
  try  
  {  
  CInternetSession*   objSession   =   new   CInternetSession(strServerName,1);  
  CFtpConnection*   objConn   =   objSession->GetFtpConnection(strServerName,strUserName,strPassword);  
    
  //objConn->GetFile(strSourPath,strDestPath,FALSE);  
  GetTree(objConn,strSourPath,strDestPath);  
    
  objConn->Close();  
  delete   objConn;  
  objSession->Close();  
  delete   objSession;  
  }  
  catch(CInternetException*   pEx)  
  {  
  TCHAR   szErr[1024];  
  if   (pEx->GetErrorMessage(szErr,   1024))  
  AfxMessageBox(szErr,   MB_OK);  
  else  
  AfxMessageBox("sdfs",   MB_OK);  
  pEx->Delete();  
  }  
   
  }  

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值