• libcurl编译使用,实现ftp功能


    Libcurl实现ftp的下载,上传功能。版本为curl-7.63.0

    1、编译vs2015

    参考资料:https://blog.csdn.net/yaojingkao/article/details/53044361

    2、libcurl传输进度参考:

    https://blog.csdn.net/u012234115/article/details/83869486

    3、libcurl使用方法参考:

    https://www.cnblogs.com/mengfanrong/p/4581068.html

    4、在搜索资料的时候,应该注意libcurl版本的问题,不同的版本,用法可能不同。

     5、断点续传:

    https://www.cnblogs.com/chang290/archive/2012/08/12/2634858.html

    官网下载:

     

    解压到本地,使用vs2015打开解决方案:

     

    选择libcurl,DLL Release,32位,进行编译

     

    编译完成后,生成的库文件libcurl.dll  和 libcurl.lib 在下面的目录中

     

    2、使用:vs2015新建测试工程:

     

    需要libcurl的头文件跟动态库。

    libcurl头文件路径:

     

    将libcurl头文件跟库文件,放到ftptest.sln解决方案下面

    在ftptest.sln同级目录下,新建include和lib目录

     

    将libcurl的头文件拷贝到include目录下

     

    将libcurl的库拷贝到lib目录下目录下

     

    将libcurl头文件加入到工程配置中:

     

    将libcurl库加入到工程配置中:

    在工程中连接libcurl库:

     

     

    对libcurl进行c++封装,测试,c++使用Qt

    头文件:

    #ifndef FTPLIBCURL_H

    #define FTPLIBCURL_H

     

    #include "curl/curl.h"

    #include "curl/easy.h"

    #include <QObject>

     

    class FtpLibCurl;

    struct CustomProgress

    {

        curl_off_t lastruntime; /* type depends on version, see above */

        CURL *curl;

        FtpLibCurl* p;

    };

     

    class FtpLibCurl : public QObject

    {

        Q_OBJECT

     

    public:

        FtpLibCurl(QObject *parent);

        ~FtpLibCurl();

     

    public:

        void getProg(qulonglong);

        void setFile(const QString&);

     

    public slots:

        void process();

        void downFile();

     

    signals:

        void finished();

        void error(QString err);

        void ftp_prog(QString);

     

    public:

        struct CustomProgress prog;

     

    private:

        qulonglong m_fileSize;

        QString m_s_percentage;

        QString m_fileName;

    };

     

    #endif // FTPLIBCURL_H

    Cpp文件:

    #include "FtpLibCurl.h"

     

    //#define F_LOCAL_FILE     "F:/1.jpg"

    //#define F_REMOTE_URL     "ftp://192.168.16.166:21//home/msj/1.jpg"

     

     

     

    size_t f_read_callback(void *ptr, size_t size, size_t nmemb, void *stream) //回调函数

    {

        curl_off_t nread;

        size_t retcode = fread(ptr, size, nmemb, (FILE*)(stream));

        nread = (curl_off_t)retcode;

        return retcode;

    }

     

    // work for both download and upload

    int progressCallback(void *p,

        curl_off_t dltotal,

        curl_off_t dlnow,

        curl_off_t ultotal,

        curl_off_t ulnow)

    {

        struct CustomProgress *progress = (struct CustomProgress *)p;

        CURL *curl = progress->curl;

        curl_off_t curtime = 0;

     

        curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME_T, &curtime);

     

        /* under certain circumstances it may be desirable for certain functionality

        to only run every N seconds, in order to do this the transaction time can

        be used */

        if ((curtime - progress->lastruntime) >= 3000000)

        {

            progress->lastruntime = curtime;

            //printf("TOTAL TIME: %f ", curtime);

        }

     

        // do something to display the progress

        //printf("UP: %ld bytes of %ld bytes, DOWN: %ld bytes of %ld bytes ", ulnow, ultotal, dlnow, dltotal);

        if (ultotal)

        {

            //printf("UP progress: %0.2f ", float(ulnow / ultotal));

            progress->p->getProg(ulnow);

        }

        if (dltotal)

        {

            //("DOWN progress: %0.2f ", float(dlnow / dltotal));

        }

           

     

     

        return 0;

    }

     

    FtpLibCurl::FtpLibCurl(QObject *parent)

        : QObject(parent)

    {

        prog = {0};

     

        m_s_percentage = QString("0%");

        m_fileName.clear();

    }

     

    FtpLibCurl::~FtpLibCurl()

    {

     

    }

     

     

     

    void FtpLibCurl::process()

    {

        CURL *pCurlhandle;

        CURLcode res;

        FILE *hd_src;

        struct stat file_info;

        curl_off_t fsize;

     

        QByteArray ba = m_fileName.toLocal8Bit();

        const char *c_str = ba.constData();

     

     

        /*1. 获取待上传文件的大小 */

        if (stat(c_str, &file_info)) {

            printf("Couldnt open '%s': %s ", c_str, strerror(errno));

            emit error(QString("local file not exist"));

            return;

        }

        fsize = (curl_off_t)file_info.st_size;

        m_fileSize = fsize;

     

        /*2. 获取待上传文件的描写叙述符 */

        hd_src = fopen(c_str, "rb");

     

        /*3. 初始化全部可能的调用*/

        curl_global_init(CURL_GLOBAL_ALL);

     

        /*4. 创建一个curlhandle*/

        pCurlhandle = curl_easy_init();

     

        if (pCurlhandle)

        {

            curl_easy_setopt(pCurlhandle, CURLOPT_USERPWD, "msj:msj");

     

            /*5.设置一个回调函数 */

            curl_easy_setopt(pCurlhandle, CURLOPT_READFUNCTION, f_read_callback);

     

            /*6.使能上传标志位 */

            curl_easy_setopt(pCurlhandle, CURLOPT_UPLOAD, 1L);

     

            /*7.指定ftpserver的url */

            QStringList path_list = m_fileName.split('/');

            QString tmp_url = "ftp://192.168.16.166:21//home/xx/" + path_list.last();

            QByteArray url_ba = tmp_url.toLocal8Bit();

            const char *url_str = url_ba.constData();

     

            curl_easy_setopt(pCurlhandle, CURLOPT_URL, url_str);

     

            /*8.指定须要上传的文件 */

            curl_easy_setopt(pCurlhandle, CURLOPT_READDATA, hd_src);

     

            /*9.设置待上传文件的大小,这个大小是上面获取到的注意:当參数

            为CURLOPT_INFILESIZE_LARGE的时候。size类型应该是curl_off_t的,

            当參数为CURLOPT_INFILESIZE的时候size应该是long类型的*/

            curl_easy_setopt(pCurlhandle, CURLOPT_INFILESIZE_LARGE,

                (curl_off_t)fsize);

     

            // set upload progress

            curl_easy_setopt(pCurlhandle, CURLOPT_XFERINFOFUNCTION, progressCallback);

            curl_easy_setopt(pCurlhandle, CURLOPT_XFERINFODATA, &prog);

            prog.p = this;

            curl_easy_setopt(pCurlhandle, CURLOPT_NOPROGRESS, 0);

     

            /*10. 開始运行我们上述设定的方法*/

            res = curl_easy_perform(pCurlhandle);

            /*11. 检查是否运行成功 */

            if (res != CURLE_OK)

            {

                fprintf(stderr, "curl_easy_perform() failed: %s ",

                    curl_easy_strerror(res));

     

                emit error(QString(curl_easy_strerror(res)));

            }

     

            /*12. 关闭pCurlhandle*/

            curl_easy_cleanup(pCurlhandle);

        }

        fclose(hd_src); /* close the local file */

                        /*13. 清除全部可能的调用*/

        curl_global_cleanup();

     

        emit finished();

    }

     

    void FtpLibCurl::getProg(qulonglong v)

    {

        int int_percentage = (v / m_fileSize)*100;

        QString tmp_percentage = QString::number(int_percentage) + "%";

        if (m_s_percentage!= tmp_percentage)

        {

            m_s_percentage = tmp_percentage;

            emit ftp_prog(tmp_percentage);

        }

       

    }

     

    void FtpLibCurl::downFile()

    {

     

    }

     

    void FtpLibCurl::setFile(const QString& s)

    {

        m_fileName = s;

    }

    测试代码:

        QThread *thread = new QThread();

        FtpLibCurl *worker = new FtpLibCurl(nullptr);

     

        worker->setFile(QString("F:/1.jpg"));

        worker->moveToThread(thread);

     

        // 错误处理

        connect(worker, SIGNAL(error(QString)), this, SLOT(errorString(QString)));

     

        // 处理数据

        connect(thread, SIGNAL(started()), worker, SLOT(process()));

     

        // 退出、删除

        connect(worker, SIGNAL(error(QString)), this, SLOT(ftp_error(QString)));

        connect(worker, SIGNAL(finished()), thread, SLOT(quit()));

        connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));

        connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));

     

        // 启动线程

        thread->start();

  • 相关阅读:
    Spring事务管理学习笔记
    写给初学前端工程师的一封信
    angularjs 自定义指令弹窗
    ng-if和ng-show的区别
    前端遇到的一些坑
    浏览器样式兼容总结
    百分比控制表格列宽,不起效
    ng-model 将时间戳转换为标准时间
    使用git和sourcetree提交代码的一些问题
    本地运行angularjs应用,提示出现跨域问题
  • 原文地址:https://www.cnblogs.com/zhangxuan/p/10187345.html
Copyright © 2020-2023  润新知