2010-11-23 2 views
5

내 C++ 프로그램에서 libcurl을 사용하여 파일을 다운로드하고 있습니다. 요청이 404이고 파일을 쓰지 않는 경우 어떻게 감지 할 수 있습니까? 코드는 다음과 같습니다 전송이 발생한 후 내가 404 응답을 삭제할 수 있지만,이 경우에도 응답을 저장하지 좋은 것libcurl 404 detection

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) { 
      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); 

      long http_code = 0; 
      curl_easy_getinfo (curl, CURLINFO_RESPONSE_CODE, &http_code); 

      curl_easy_cleanup(curl); 
      fclose(fp); 
     } 
     else { 
      cout<<"GameImage::DownloadImage; Couldn't open output file"<<endl; 
     } 
    } 
} 

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; 
} 

.

답변

4

당신은 CURLOPT_FAILONERRORtrue로 설정하고, HTTP 서버가 >= 400 오류 코드를 반환하는 경우이 반환됩니다 CURLE_HTTP_RETURNED_ERROR

에 대해 확인할 수 있습니다. 특정 HTTP 응답 코드를 가져올 수는 없지만 원하는 것을 수행하기에 충분해야합니다.

+0

파일은 여전히 ​​있지만 비어 있습니다. curl_easy_setopt (curl, CURLOPT_FAILONERROR, true)를 추가했습니다. 나는 오류가 발생해도 상관 없다. 나는 파일을 남기고 싶지 않다. – zombor

+0

질문을 지금 코드대로 업데이트 할 수 있습니까? – Alex

+0

완료. 나는 그것이 초기 fp = fopen (outfilename.c_str(), "wb") 때문이라고 생각한다. 파일 핸들을 생성합니다. – zombor

1

나는 오래된 게시물 인 것을 알고 있지만, 여러분이하는 에러는 curl_easy_perform의 반환 값을 확인하지 않는다는 것입니다. CURLOPT_FAILONERROR를 설정해도 프로그램이 중단되지 않고 대신 res라는 이름의 반환 변수를 통해 오류를 알립니다. 빈 파일을 없애려면 다음과 같이 할 수 있습니다.

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; 
}