C++使用libcurl实现FTP客户端功能

curl/libcurl 下载及编译

下载源码

github 地址 : https://github.com/curl/curl
在这里插入图片描述

Release 版本下载地址: https://github.com/curl/curl/releases/
在这里插入图片描述
下载 “curl-8.0.1.zip” 包,并解压:

打开 projects/Windows 目录下对应 VS 的工程文件,比如我打开的是 VC14.10 的。
在这里插入图片描述
在这里插入图片描述

源码编译

VS2019 打开工程,然后设置工程参数。

C/C++设置

预处理器选项中,将USE_LIBSSH、USE_LIBSSH2等宏去掉。
在这里插入图片描述
链接器

在输入选项中,将libssl.lib相关的依赖都取消掉。
在这里插入图片描述
生成库
在这里插入图片描述
在这里插入图片描述

MFC示例项目

MFC项目配置

添加头文件包含:
在这里插入图片描述
设置预处理器:
在这里插入图片描述
设置链接器:
在这里插入图片描述
设置依赖库:
在这里插入图片描述

MFC源码


/*------------------------------------------------------------------
 *                        官方示例代码,移植过来
 *-----------------------------------------------------------------*/
//---- common progress display ---- //
struct CustomProgress
{
    curl_off_t lastruntime; /* type depends on version, see above */
    CURL* curl;
};

//---- upload related ---- //
//parse headers for Content-Length
size_t getContentLengthFunc(void* ptr, size_t size, size_t nmemb, void* stream)
{
    int r;
    long len = 0;

    r = sscanf((const char*)ptr, "Content-Length: %ld\n", &len);
    if (r) /* Microsoft: we don't read the specs */
        *((long*)stream) = len;
    return size * nmemb;
}

//discard already downloaded data
size_t discardFunc(void* ptr, size_t size, size_t nmemb, void* stream)
{
    return size * nmemb;
}

//read data to upload
size_t readfunc(void* ptr, size_t size, size_t nmemb, void* stream)
{
    FILE* f = (FILE*)stream;
    size_t n;
    if (ferror(f))
        return CURL_READFUNC_ABORT;
    n = fread(ptr, size, nmemb, f) * size;
    return n;
}


//do upload, will overwrite existing file
int FtpUpload(const char* remote_file_path,
    const char* local_file_path,
    const char* username,
    const char* password,
    long timeout, long tries = 3)
{
    //init curl handle
    curl_global_init(CURL_GLOBAL_ALL);
    CURL* curlhandle = curl_easy_init();

    //get user_key pair
    char user_key[1024] = { 0 };
    sprintf(user_key, "%s:%s", username, password);

    FILE* file;
    long uploaded_len = 0;
    CURLcode ret = CURLE_GOT_NOTHING;
    file = fopen(local_file_path, "rb");
    if (file == NULL)
    {
        perror(NULL);
        return 0;
    }
    //使能上传功能
    curl_easy_setopt(curlhandle, CURLOPT_UPLOAD, 1L);      
    curl_easy_setopt(curlhandle, CURLOPT_URL, remote_file_path);
    curl_easy_setopt(curlhandle, CURLOPT_USERPWD, user_key);
    if (timeout) {
        curl_easy_setopt(curlhandle, CURLOPT_FTP_RESPONSE_TIMEOUT, timeout);
    }
    curl_easy_setopt(curlhandle, CURLOPT_HEADERFUNCTION, getContentLengthFunc);
    curl_easy_setopt(curlhandle, CURLOPT_HEADERDATA, &uploaded_len);
    curl_easy_setopt(curlhandle, CURLOPT_WRITEFUNCTION, discardFunc);
    curl_easy_setopt(curlhandle, CURLOPT_READFUNCTION, readfunc);
    curl_easy_setopt(curlhandle, CURLOPT_READDATA, file);
    curl_easy_setopt(curlhandle, CURLOPT_FTPPORT, "-"); /* disable passive mode */
    curl_easy_setopt(curlhandle, CURLOPT_FTP_CREATE_MISSING_DIRS, 1L);

    // upload: 断点续传
    for (int c = 0; (ret != CURLE_OK) && (c < tries); c++)
    {
        /* are we resuming? */
        if (c)
        {   /* yes */
            /* determine the length of the file already written */
            /*
            * With NOBODY and NOHEADER, libcurl will issue a SIZE
            * command, but the only way to retrieve the result is
            * to parse the returned Content-Length header. Thus,
            * getContentLengthfunc(). We need discardfunc() above
            * because HEADER will dump the headers to stdout
            * without it.
            */
            curl_easy_setopt(curlhandle, CURLOPT_NOBODY, 1L);
            curl_easy_setopt(curlhandle, CURLOPT_HEADER, 1L);
            ret = curl_easy_perform(curlhandle);
            if (ret != CURLE_OK)
                continue;
            curl_easy_setopt(curlhandle, CURLOPT_NOBODY, 0L);
            curl_easy_setopt(curlhandle, CURLOPT_HEADER, 0L);
            fseek(file, uploaded_len, SEEK_SET);
            curl_easy_setopt(curlhandle, CURLOPT_APPEND, 1L);
        }
        else
            curl_easy_setopt(curlhandle, CURLOPT_APPEND, 0L);

        ret = curl_easy_perform(curlhandle);
    }
    fclose(file);

    int curl_state = 0;
    if (ret == CURLE_OK)
    {
        curl_state = 1;
    }
    else
    {
        fprintf(stderr, "%s\n", curl_easy_strerror(ret));
        curl_state = 0;
    }

    //推出
    curl_easy_cleanup(curlhandle);
    curl_global_cleanup();

    return curl_state;
}


/*------------------------------------------------------------------
 *                       MFC对话框调用接口示例
 *-----------------------------------------------------------------*/
//MFC对话框《确定》按钮槽函数
void CLibcurlftpcliDlg::OnBnClickedOk()
{
	//TODO: 通过libcurl远程获取FTP服务器上的PlanPath-0911.xml文件

	//FTP远程文件位置及服务器IP地址
    std::string strRemoteFilePath = "ftp://192.168.32.165:21/myfile/PlanPath-0911.xml";

	//本地存放路径
    std::string strLocalFilePath = "C:/Users/MG/Desktop/AC/tongji/xmlconfig/PlanPath-0911.xml";
    
    //获取文件
    int iRet = FtpUpload(strRemoteFilePath.c_str(), strLocalFilePath.c_str(), "root", "root123", 1);
}

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值