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