函数功能: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)
{