환경 : ubuntu 12.04 LTS 이번 포스트에서 얻는것, curl_easy_getinfo의 간단한 이해와 url이 잘못되었을 경우에 생성된 파일 처리 방법 이 검색의 이유는 잘못된 URL을 입력해도 파일이 생성되는 것일 방지하기 위해서 getinfo로 시작해서 remove로 끝나는 과정을 적인 것입니다. 시작합니다~~ ^^ dev kyu |
curl_easy_getinfo를 사용해서 작성한 것, 코드
curl_easy_getinfo로 동작하기 이전에 상태를 확인하려 했는데 아래의 블로그를 들어가보니 curl을 동작 시킨 이후에 확인할 수 있다. 음.. 파일 열기 전에 확인하고 싶은데...
(아래 블로그에서 갖고온 코드와 주소)
#include <curl/curl.h> int curl_header_flag = 0; char *last_use_url; char *cpy_last_url; cpy_last_url = (char *)malloc(1000); memset(cpy_last_url , 0x00, 1000); CURL *curl_handle; struct MemoryStruct chunk; chunk.memory=NULL; chunk.size = 0; curl_global_init(CURL_GLOBAL_ALL); curl_handle = curl_easy_init(); curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, 10); curl_easy_setopt(curl_handle, CURLOPT_URL, addr); curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, WriteMemoryCallback); curl_easy_setopt(curl_handle, CURLOPT_HEADER , WriteMemoryCallback); curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&chunk); curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)"); curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1); curl_easy_perform(curl_handle); curl_easy_getinfo(curl_handle, CURLINFO_RESPONSE_CODE, &curl_header_flag); curl_easy_getinfo(curl_handle, CURLINFO_EFFECTIVE_URL, &last_use_url);
strcpy(cpy_last_url, last_use_url); curl_easy_cleanup(curl_handle); fprintf(stderr, "[Report] CURL Header status [%d]\n", curl_header_flag); fprintf(stderr, "[Report] CURL Last url [%s]\n", cpy_last_url); [출처] curl_easy_getinfo() 사용|작성자 조르프
|
http://blog.naver.com/handukgyu?Redirect=Log&logNo=100124397913
-----------------------------------------------------------------------------------------------------------------------------------------------------
그냥 이건 참고용.. 코드 쓰다보면 그냥 이렇겠구나~ 한거를 어떤 분이 한글로 정리해주신 것.
curl 라이브러리 사용하기
curl_blogal_init() : 라이브러리 초기화
curl_easy_init() : context 생성
curl_easy_setopt() : 설정
curl_easy_perform() : 페이지 요청 및 콜백 함수들 대기
curl_easy_getInfo() : 페이지의 각종 요소 값들 받기 (해더, 타입, 크기 등등등)
curl_easy_strerror() : 에러 발생시 무슨 에러?
curl_easy_cleanup() : context 삭제
curl_global_cleanup() : 라이브러리 삭제
( http://manhdh.blog.me/120146975838 )
------------------------------------------------------------------------------------------------------------------------------------------------------
여기서 보면 curl_easy_getinfo를 사용하는 것을 볼 수 있다.
#include <curl/curl.h>
#include <curl/easy.h>
int GetConfigFile ( void ) {
} |
그런데 이 코드들도 파일을 열기 전, 그러니깐 콜백함수의 FILE을 open하기 전에 확인하는 건 없다... 아예 없는 건가?
아예 없다면 콜백 함수 내에서 확인을 하여서 생성한 파일을 삭제 하던지 취소하던지 해야하는데.. 흠...
------------------------------------------------------------------------------------------------------------------------------------------------------
using namespace std; #define HTTP_ONLY extern "C" { #include "../curl-7.20.1/curl-7.20.1/include/curl/curl.h" } #include<cstdio> #include<iostream> #include<string> #include<sstream> char *print_cookie(CURL *curl) { char *ret = (char*)malloc(1000); struct curl_slist *cookie_list, *t = NULL; char *p = NULL, *p1 = NULL, *ptr = ret; memset(ret, 0, 1000); curl_easy_getinfo(curl, CURLINFO_COOKIELIST, &cookie_list); t = cookie_list; if (!t) { free(ret); ret = NULL; } while (t) { printf("%s\n", t->data); p = strrchr(t->data, '\t'); *p = '\0'; p++; p1 = strrchr(t->data, '\t'); p1++; strcpy(ptr, p1); strcat(ptr, "="); strcat(ptr, p); strcat(ptr, "; "); ptr += strlen(ptr); t = t->next; } curl_slist_free_all(cookie_list); return ret; } struct html_context_data { char* data; // 버퍼 size_t size; // 사이즈 }; size_t callback_write_memory(void *ptr, size_t size, size_t nmemb, void *stream) { size_t realsize = size * nmemb; html_context_data *mem = (html_context_data *)stream; mem->data = (char*)realloc(mem->data, mem->size + realsize + 1); if (mem->data) { memcpy(&(mem->data[mem->size]), ptr, realsize); mem->size += realsize; mem->data[mem->size] = '\0'; } return realsize; } static void free_html_context_data(html_context_data *p) { p ? (free(p->data), p->data = NULL, p->size = 0) : 1; } void get_post_data(std::ostringstream& postBuf, const char** pp) { while( NULL != *pp ) { // curl_escape( {string} , 0 ): replace special characters // (such as space, "&", "+", "%") with HTML entities. // ( 0 => "use strlen to find string length" ) // remember to call curl_free() on the strings on the way out char* key = curl_escape( pp[0] , 0 ); char* val = curl_escape( pp[1] , 0 ); postBuf << key << "=" << val << "&" ; pp += 2 ; // the cURL lib allocated the escaped versions of the // param strings; we must free them here curl_free( key ) ; curl_free( val ) ; } postBuf << std::flush ; } void curl_post(const char* url, const char** postArrayData) { const char* targetUrl = url; // curl 를 초기화 한다. curl_global_init( CURL_GLOBAL_ALL ) ; // context 를 생성한다. CURL* ctx = curl_easy_init() ; if( NULL == ctx ){ printf("curl context 생성 실패\n"); return; } /* BEGIN: configure the handle: */ // 쿠키 값을 비워주기( 혹시 쿠키를 받는 사이트일 경우 필요 ) curl_easy_setopt(ctx, CURLOPT_COOKIEFILE, ""); // 요청 url curl_easy_setopt( ctx , CURLOPT_URL, targetUrl ) ; // 요청한 결과 data를 메모리에 받아 오기 html_context_data data = {0, 0}; curl_easy_setopt(ctx, CURLOPT_WRITEDATA, &data); curl_easy_setopt(ctx, CURLOPT_WRITEFUNCTION, callback_write_memory ); // 데이터를 표준출력으로 내보내기 // curl_easy_setopt( ctx , CURLOPT_WRITEDATA , stdout ) ; // 헤더 셋팅하기 curl_slist* header = NULL ; header = curl_slist_append( header , "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705) " ) ; header = curl_slist_append( header , "Content-Type: application/x-www-form-urlencoded" ) ; curl_easy_setopt( ctx , CURLOPT_HTTPHEADER , header ) ; // POST Data 설정 // notice the URL-unfriendly characters (such as "%" and "&") // URL에서는 '%', '&', ' '와 같은 문자를 URL encoding 시켜줘야 한다. // curl_escape 함수를 이용해서 인코딩할 수 있다. std::ostringstream postBuf ; get_post_data( postBuf, postArrayData); const std::string postData = postBuf.str(); curl_easy_setopt( ctx , CURLOPT_POSTFIELDS , postData.c_str() ) ; // post 방식으로 요청할 것인지 셋팅 curl_easy_setopt( ctx , CURLOPT_POST , 1 ) ; // 사이트 실제 처리 요청 CURLcode rc = curl_easy_perform( ctx ) ; if( CURLE_OK != rc ){ std::cerr << '\t' << "에러 : " << curl_easy_strerror( rc ) << std::endl ; } // 쿠키 있으면 출력 print_cookie( ctx ); // html 리턴 코드 보기 long statLong; curl_easy_getinfo( ctx, CURLINFO_HTTP_CODE, &statLong); // data 해당 페이지 출력 std::cout << data.data << std::endl; // 사용한 메모리 해제 free_html_context_data( &data ); // 헤더 리스트 해제 curl_slist_free_all( header ) ; // context 해제 curl_easy_cleanup( ctx ) ; // lib 해제 curl_global_cleanup() ; } |
[출처] libcurl post 요청 예제|작성자 규승
( http://blog.naver.com/laster40?Redirect=Log&logNo=107370315 )
------------------------------------------------------------------------------------------------------------------------------------------------------
어떤 분이 에러코드 뜬다고 올린 질문인데, 저는 에러를 띄우고 싶어서 한번 찾아봤어요. 그랬더니 원하는게 있긴 있네요 ㅎㅎㅎㅎㅎㅎㅎㅎ
동일한 질문이 있어서 갖고 왔어요, 이 질문 답변자 분의 말씀을 들어보니 curl_easy_perform의 return값을 확인해서 그 값이 틀릴 경우엔 생성했던 파일을 지우라네요, 결국은 미리 확인하는 방법은 일단 없는걸로,, 그렇다고 함수 하나 만들어서 미리 받아와 보기도 좀 그렇구요.. 일단 끝ㅋ
파일을 지우는 경우엔 별다른 문제는 없을 듯 하다. 대부분 call back함수 내에서 open과 close가 이루어지기 때문에 main에서 확인하여 지우는 것엔 별다른 문제는 없다.
이제 solution격인 소스를 찾았으니깐 코딩 시작~~ 하기 전에 remove함수부터 찾고...
void GameImage::DownloadImage(string file_name) {
string game_name;
game_name = file_name.substr(file_name.find_last_of("/")+1);
CURL *curl;
FILE *fp;
CURLcode res;
string url = "http://site/"+game_name+".png";
string outfilename = file_name+".png";
cout<<"INFO; attempting to download "<<url<<"..."<<endl;
curl = curl_easy_init();
if (curl) {
cout<<"INFO; downloading "<<url<<"..."<<endl;
fp = fopen(outfilename.c_str(), "wb");
cout<<"INFO; trying to open "<<outfilename<<" for file output"<<endl;
if (fp == NULL) {
cout<<"GameImage::DownloadImage; Couldn't open output file"<<endl;
curl_easy_cleanup(curl);
return;
}
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, GameImage::WriteData);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
curl_easy_setopt(curl, CURLOPT_FAILONERROR, true);
res = curl_easy_perform(curl);
fclose(fp);
if (res != CURLE_OK) {
cout<<"GameImage::DownloadImage; Failed to download file"<<endl;
remove(outfilename.c_str());
}
curl_easy_cleanup(curl);
}
}
size_t GameImage::WriteData(void *ptr, size_t size, size_t nmemb, FILE *stream) {
size_t written;
written = fwrite(ptr, size, nmemb, stream);
return written;
}
( http://stackoverflow.com/questions/4252533/libcurl-404-detection )
------------------------------------------------------------
remove 함수, 찾아보니깐 딱이네 ㅎㅎ
그동안 찾던 잘못된 URL에 대한 예외처리 해주러 고고~~
remove
int remove ( const char * filename );
This is an operation performed directly on a file identified by its filename; No streams are involved in the operation.
Proper file access shall be available.
'소프트웨어' 카테고리의 다른 글
[javascript] chapter6. Objects _발번역 (0) | 2014.01.22 |
---|---|
[c++] ifndef / endif (0) | 2014.01.22 |
[curl] curl_easy_getinfo (1) (0) | 2014.01.21 |
[c++] file path 설정 (0) | 2014.01.20 |
[ubuntu] T440P NVIDIA 드라이버 잡는 방법(bumblebee) (0) | 2014.01.06 |