libcurl上传下载文件

 

 

/*!
* Email: guxuanqing@163.com
* Auth:  guxuanqing
* Date:  05/20/2020
* File:  httpFileTransmission.cpp
* Class: CHttpFileTransmission (if applicable)
* variable:
* Brief:
* Note:
 */

#include "httpFileTransmission.h"

CHttpFileTransmission::CHttpFileTransmission()
{

}

//重写把数据读入上传数据流函数
size_t read_file(void* buff, size_t size, size_t nmemb, void* userp)
{
    size_t sizes = fread(buff, size, nmemb, (FILE *)userp);
    return sizes;
}

int CHttpFileTransmission::upload_file(const char* url, const char* file_name)
{
    if ("" == url || "" == file_name)
    {
        std::cout << "url地址或文件名为空,操作失败!" << std::endl;
        return -1;
    }
    CURLcode res;    //easy_handle定义的一些错误码

    //初始化libcurl
    res = curl_global_init(CURL_GLOBAL_ALL);
    if (res != CURLE_OK)
    {
        std::cerr << "init libcurl failed." << std::endl;
        return -1;
    }

    //获取要上传的文件指针
    FILE* r_file = fopen(file_name, "rb");
    if (0 == r_file)
    {
        std::cerr << "the file " << file_name << " that you will read is not exist" << std::endl;
        return -1;
    }

    CURL* easy_handle;

    easy_handle = curl_easy_init();
    if (0 == easy_handle)
    {
        std::cout << "get a easy_handle handle fail!" << std::endl;
        fclose(r_file);
        curl_global_cleanup();
        curl_easy_cleanup(easy_handle);
        return -1;
    }

    // 获取文件大小
    fseek(r_file, 0, 2);
    int file_size = ftell(r_file);
    rewind(r_file);

    curl_easy_setopt(easy_handle, CURLOPT_URL, url);        //获取URL地址
    curl_easy_setopt(easy_handle, CURLOPT_UPLOAD, true);    //告诉easy_handle是做上传操作
    curl_easy_setopt(easy_handle, CURLOPT_READFUNCTION, &read_file);    //调用重写的读文件流函数
    curl_easy_setopt(easy_handle, CURLOPT_READDATA, r_file);    //往read_file()函数中传入用户自定义的数据类型
    curl_easy_setopt(easy_handle, CURLOPT_INFILE, r_file);        //定位作为上传的输入文件
    curl_easy_setopt(easy_handle, CURLOPT_INFILESIZE, file_size);    //上传的字节数

    //执行设置好的操作
    res = curl_easy_perform(easy_handle);

    //获取HTTP错误码
    int HTTP_flag = 0;
    curl_easy_getinfo(easy_handle, CURLINFO_RESPONSE_CODE , &HTTP_flag);

    //一般清理动作
    fclose(r_file);
    curl_global_cleanup();
    curl_easy_cleanup(easy_handle);

    std::cout << "操作本地文件:" << file_name << "; url:" << url << ".";
    //检测HTTP错误码和执行操作结果
    if ((200 != HTTP_flag) || (CURLE_OK != res))//if ((0 != check_error(HTTP_flag)) || (CURLE_OK != res))
    {
        std::cout << "失败!" << std::endl;
        return -1;
    }
    else
    {
        std::cout << "成功!" << std::endl;
        return 0;
    }
}

//WRITEFUNCTION回调函数的实现,在这里只做简单的处理
size_t process_data(void *buffer, size_t size, size_t nmemb, std::string& user_p)
{
    user_p = (char*)buffer;

    return nmemb;
}


const int FILE_EXIST = 200;


int CHttpFileTransmission::down_file(const char *url/*, const char *down_file_name*/, const string save_name)
{
    // 初始化libcurl
    CURLcode return_code;
    return_code = curl_global_init(CURL_GLOBAL_ALL);
    if (CURLE_OK != return_code)
    {
        cerr << "init libcurl failed." << endl;
        curl_global_cleanup();
        return -1;
    }

    // 获取easy handle
    CURL *easy_handle = curl_easy_init();
    if (NULL == easy_handle)
    {
        cerr << "get a easy handle failed." << endl;
        curl_easy_cleanup(easy_handle);
        curl_global_cleanup();
        return -1;
    }

    // 设置easy handle属性
    return_code = curl_easy_setopt(easy_handle, CURLOPT_URL, url);

    //设置回调函数
    return_code = curl_easy_setopt(easy_handle, CURLOPT_WRITEFUNCTION, &process_data);

    //回调函数的额外参数
    std::string connectx;
    return_code = curl_easy_setopt(easy_handle, CURLOPT_WRITEDATA, &connectx);

    // 执行数据请求
    return_code = curl_easy_perform(easy_handle);

    //判断获取响应的http地址是否存在,若存在则返回200,400以上则为不存在,一般不存在为404错误
    int retcode = 0;
    return_code = curl_easy_getinfo(easy_handle, CURLINFO_RESPONSE_CODE , &retcode);
    if (CURLE_OK == return_code && FILE_EXIST == retcode)
    {
        double length = 0;
        return_code = curl_easy_getinfo(easy_handle, CURLINFO_CONTENT_LENGTH_DOWNLOAD , &length);
        printf("ret:%d len:%lf\n", return_code, length);
        FILE *fp = fopen(save_name.c_str(), "wb+");
        int retWLen = fwrite(connectx.c_str(), 1, length, fp);    //返回实际写入文本的长度,若不等于length则写文件发生错误.
        printf("retWlen:%d\n", retWLen);
        fclose(fp);
    }
    else
    {
        std::cout << "请求的文件不存在!" << std::endl;
        curl_easy_cleanup(easy_handle);
        curl_global_cleanup();
        return -1;
    }

    // 释放资源
    curl_easy_cleanup(easy_handle);
    curl_global_cleanup();

    return 0;
}

int main(int argc, char *argv[])
{
    CHttpFileTransmission http_down_file;

    const char *url = argc == 2 ? argv[1] : "https://dumps.wikimedia.org/zhwiki/20200601/zhwiki-20200601-stub-articles1.xml.gz";
//    const char *down_file_name;
    const string save_name("zhwiki20200601.gz");
    http_down_file.down_file(url, save_name.c_str());

    printf("hello world!\n");
    return 0;
}

 

 

g++ -g httpFileTransmission.cpp -o xdownload -lcurl

 

posted @ 2019-12-14 10:04  PKICA  阅读(640)  评论(0编辑  收藏  举报