zoukankan      html  css  js  c++  java
  • 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
    ", return_code, length);
            FILE *fp = fopen(save_name.c_str(), "wb+");
            int retWLen = fwrite(connectx.c_str(), 1, length, fp);    //返回实际写入文本的长度,若不等于length则写文件发生错误.
            printf("retWlen:%d
    ", 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!
    ");
        return 0;
    }
    g++ -g httpFileTransmission.cpp -o xdownload -lcurl
  • 相关阅读:
    C#在window服务配置Log4Net.dll
    致于即将逝去的2108年,2019年您好
    关于:未能加载文件或程序集“ICSharpCode.SharpZipLib”或它的某一个依赖项异常的解决方案
    Vs 中关于项目中的某 NuGet 程序包还原失败:找不到“xxx”版本的程序包“xxx”
    Git分布式版本控制器常用命令和使用
    微信公众平台网页登录授权多次重定向跳转,导致code使用多次问题
    Visual Studio高效实用的扩展工具、插件
    关于微信企业付款到零钱X509Certificate2读取证书信息,发布到服务器访问不到的解决方案
    关于ASP.NET MVC 项目在本地vs运行响应时间过长无法访问时,解决方法!
    彻底关闭windows10自动更新解决方案
  • 原文地址:https://www.cnblogs.com/guxuanqing/p/12038253.html
Copyright © 2011-2022 走看看