wangchenxicool

博客园 首页 联系 管理

程序要求显示在图形界面下显示下载进度,所以今天用FtpLib临时做了一个MFC程序,运行效果如下:

 

大体流程:
1
、输入要下载的文件以及要保存到本地的文件路径,然后触发Start
2
、把下载任务推入到utShareData的任务队列中(Queue先进先出);
3
、工作线程从utShareData的任务队列中获取任务,开始FTP
4
、在Ftp过程中,通过PostMessage发送进度消息给主窗口;
5
、主窗口响应此消息然后进行相应的窗口显示。

关键点:
MyFtp.h封装了FtpLib的部分功能:

class MyFtp
{
private:

string _host;
string _user;
string _password;
string _err;
public:
MyFtp(
const string& host, const string& user, const string& password);
~MyFtp();
public:
bool connect();
bool down(const string& sourceFileName, const string& targetFileName);
string getErr();
};
实现:
MyFtp
* _ftp;

static netbuf *conn = NULL;

struct REMFILE {
struct REMFILE *next;
int fsz;
char *fnm;
};

static int log_progress(netbuf *ctl, int xfered, void *arg)
{
struct REMFILE *f = (struct REMFILE *) arg;
int pct = (int)(xfered*1.0/f->fsz*100);
//printf("%s %3d%%/r", f->fnm, pct);
//fflush(stdout);
::PostMessage((HWND)(AfxGetApp()->GetMainWnd()->GetSafeHwnd()),WM_PROGRESS,pct,NULL);
return 1;
}

MyFtp::MyFtp(
const string& host, const string& user, const string& password)
{
_host
= host;
_user
= user;
_password
= password;
FtpInit();
}

MyFtp::
~MyFtp()
{
if (conn)

FtpClose(conn);
}

bool MyFtp::connect()
{
if (!FtpConnect(_host.c_str(), &conn))
{
_err
= ftplib_lastresp;
return false;
}
if (!FtpLogin(_user.c_str(), _password.c_str(), conn))
{
_err
= FtpLastResponse(conn);
return false;
}
return true;
}

bool MyFtp::down(const string& sourceFileName, const string& targetFileName)
{
int sts=0;
int fsz;

if (!connect())
return false;
FtpOptions(FTPLIB_CALLBACK, (
long) NULL, conn);

struct REMFILE *f;
f
= (struct REMFILE *) malloc(sizeof(struct REMFILE));
memset(f,
0,sizeof(struct REMFILE));
f
->fnm = strdup(sourceFileName.c_str());
if (!FtpSize(f->fnm, &fsz, 'I', conn))
fsz
= 0;
f
->fsz = fsz;
fsz
= fsz/100;
if (fsz)
{
FtpOptions(FTPLIB_CALLBACK, (
long) log_progress, conn);
FtpOptions(FTPLIB_IDLETIME, (
long) 1000, conn);
FtpOptions(FTPLIB_CALLBACKARG, (
long) f, conn);
FtpOptions(FTPLIB_CALLBACKBYTES, (
long) fsz, conn);
}
sts
= FtpGet(targetFileName.c_str(),f->fnm,'I',conn);
if (sts)

::PostMessage((HWND)(AfxGetApp()
->GetMainWnd()->GetSafeHwnd()),WM_PROGRESS,100,NULL);
//printf("%s retrieved/n",f->fnm);
free(f->fnm);
free(f);

if (!sts)
{
_err
= "ftp error: ";
_err
= _err + FtpLastResponse(conn);
return false;
}
return true;
}

string MyFtp::getErr()
{
return _err;
}


这其中利用了PostMessage向主窗口发送进度消息:
::PostMessage((HWND)(AfxGetApp()->GetMainWnd()->GetSafeHwnd()),WM_PROGRESS,100,NULL);

线程还是用我一直使用的WorkThread来实现。
主窗口中响应进度消息的函数如下:

LRESULT CFtpAppDlg::OnProgress(WPARAM wParam,LPARAM lParam)
{
int progress=(int)wParam;
string str = "have download ";
str
= str + TPub::intToString(progress) + "%";
m_list.ResetContent();
m_list.AddString(str.c_str());
UpdateData(FALSE);
return 0;
}

 

posted on 2011-08-31 08:29  wangchenxicool  阅读(784)  评论(0)    收藏  举报