2010-11-23 3 views
5

Я делаю загрузку файла с помощью libcurl в моей программе на C++. Как я могу определить, является ли запрос 404, а не писать файл? Код:libcurl 404 обнаружение

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

Я могу удалить ответ 404 после передачи, но было бы неплохо даже не сохранять ответ.

ответ

4

Вы можете проверить на CURLE_HTTP_RETURNED_ERROR

Это возвращается, если CURLOPT_FAILONERROR установлен в true и сервер HTTP возвращает код ошибки, который >= 400. Вы не можете получить конкретный код ответа HTTP, но этого должно быть достаточно, чтобы выполнить то, что вы хотите.

+0

Я все еще получаю файл, но теперь он пуст. Я добавил curl_easy_setopt (curl, CURLOPT_FAILONERROR, true); Мне все равно, что произошла ошибка, я просто не хочу, чтобы файл остался позади. – zombor 2010-11-23 04:19:15

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