博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

ftplib实战-下载

Posted on 2009-04-30 15:32  海岛  阅读(786)  评论(0编辑  收藏  举报

程序要求显示在图形界面下显示下载进度,所以今天用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;
}