最近使用C++做一些编程,JAVA中采用HTTP协议通信很简单,我们熟知的HTTPClient就可以完成通信。在C++中BOOST库仅仅将TCP/UDP协议进行了很好的封装,但是HTTP需要我们自己在编写一部分代码才能很好的同步HTTP来完成客户端与服务器端的信息交互。libcurl对HTTP等协议进行了很好的封装,于是采用libcurl来完成图片上传的功能。
1.libcurl简单认识
libcurl支持用不同的协议连接和沟通不同的服务器,其支持http, https, ftp, gopher, telnet, dict, file, 和ldap 协议。libcurl是C++中比较好的网络交互的库。
libcurl下载地址为:http://curl.haxx.se/download.html
libcurl 在线API地址为:http://curl.haxx.se/libcurl/c/
libcurl 接口介绍(中文)为:http://blog.csdn.net/fengshuiyue/article/details/39530093
2.libcurl图片上传源码
InnoVSSImgSendStateType InnoVSSImgNetStorage::NetStorageImg(PicStorageModel& picStorageModel) { curl = curl_easy_init(); multi_handle = curl_multi_init(); int still_running; struct curl_httppost *formpost=NULL; struct curl_httppost *lastptr=NULL; struct curl_slist *headerlist=NULL; static const char buf[] = "Expect:"; curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "sendfile", CURLFORM_FILE, picStorageModel.picInfo.localPath.c_str(), CURLFORM_END); curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "filename", CURLFORM_COPYCONTENTS, picStorageModel.picInfo.fullView.c_str(), CURLFORM_END); std::string imageInfo; picStorageModel.postInfo.getImageInfoXml(imageInfo); imageInfo = StringEncode::GBKToUTF8(imageInfo); curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "imageInfo", CURLFORM_COPYCONTENTS, imageInfo.c_str(), CURLFORM_END); std::string urlPath = picStorageModel.urlRequestPath; //headerlist = curl_slist_append(headerlist, "Accept-Encoding:UTF-8"); //headerlist = curl_slist_append(headerlist, "Content-type: application/form-data;charset:UTF-8"); headerlist = curl_slist_append(headerlist, buf); if(curl && multi_handle) { curl_easy_setopt(curl, CURLOPT_URL, urlPath.c_str()); curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist); curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writer); //curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION,headerfunction); ImgNetStorageResultModel resultModel; resultModel.picStorageModel = picStorageModel; resultModel.imgNetStorage = this; curl_easy_setopt(curl, CURLOPT_WRITEDATA, &resultModel); curl_multi_add_handle(multi_handle, curl); CURLMcode curlm_code = CURLM_CALL_MULTI_PERFORM; curlm_code = curl_multi_perform(multi_handle, &still_running); int count = 0; int responseCode = 0; do { struct timeval timeout; int rc; fd_set fdread; fd_set fdwrite; fd_set fdexcep; int maxfd = -1; long curl_timeo = -1; FD_ZERO(&fdread); FD_ZERO(&fdwrite); FD_ZERO(&fdexcep); timeout.tv_sec = 1; timeout.tv_usec = 0; curl_multi_timeout(multi_handle, &curl_timeo); if(curl_timeo >= 0) { timeout.tv_sec = curl_timeo / 1000; if(timeout.tv_sec > 1) timeout.tv_sec = 1; else timeout.tv_usec = (curl_timeo % 1000) * 1000; } curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd); rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout); switch(rc) { case -1: count++; break; case 0: default: LOGD << "正在上传图片....." << zhxy_log::endl; curlm_code = curl_multi_perform(multi_handle, &still_running); if (curlm_code == CURLM_OK){ CURLcode res = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &responseCode); } break; } } while(still_running&&count < _adapterConfig.timeOutCount); //if (curlm_code == CURLM_OK) { // long code; // CURLcode res = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code); // long connectCode; // res = curl_easy_getinfo(curl, CURLINFO_HTTP_CONNECTCODE, &connectCode); // LOGD << "connectCode:" << connectCode << zhxy_log::endl; //} curl_formfree(formpost); curl_slist_free_all (headerlist); curl_multi_cleanup(multi_handle); curl_easy_cleanup(curl); multi_handle = NULL; curl = NULL; if (curlm_code != CURLM_OK) { LOGD << "curlm_code:" << curlm_code << "\n" <<curl_multi_strerror(curlm_code); return InnoVSSImgSendStateTypes::Failed; } if (responseCode != 200) { return InnoVSSImgSendStateTypes::Failed; } if (count>=_adapterConfig.timeOutCount) { return InnoVSSImgSendStateTypes::Failed; }else{ return InnoVSSImgSendStateType::Success; } } }
1)在调试中发现不管图片服务器是否开启,curl_multi_perform(multi_handle, &still_running);返回值一直是成功,通过返回值无法捕获到上传是否成功。
2)代码中可以通过curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &responseCode);获取http相应值,在退出循环后判断responseCode是否为200,是则上传成功,否则上传失败
原文地址:http://blog.csdn.net/fengshuiyue/article/details/39529887