• ftplib实战下载


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

  • 相关阅读:
    Spring Boot启用Swagger2
    Springboot 注解最全详解
    spring-boot-starter-data-jpa 解析
    springboot 微信支付
    springboot整合PageHelper
    SpringBoot配置HTTPS,并实现HTTP访问自动转HTTPS访问
    Springboot 发送短信验证码
    Java volatile关键字的作用
    Android兼容性测试应该怎么做逼格更高呢?
    hadoop日志【2】
  • 原文地址:https://www.cnblogs.com/tianfu/p/1447048.html
Copyright © 2020-2023  润新知