2010-11-23 13 views
5

Estoy haciendo una descarga de archivos con libcurl en mi programa de C++. ¿Cómo puedo detectar si la solicitud es un 404 y no escribir el archivo? El código es:detección de 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; 
} 

Puedo eliminar la respuesta 404 después de la transferencia, pero sería bueno ni siquiera guardar la respuesta.

Respuesta

4

Puede comprobar contra CURLE_HTTP_RETURNED_ERROR

Esto se devuelve si CURLOPT_FAILONERROR se establece en true y el servidor HTTP devuelve un código de error que es >= 400. No puede obtener el código de respuesta HTTP específico, pero debería ser suficiente para lograr lo que desea.

+0

Todavía obtengo un archivo, pero está vacío ahora. Agregué curl_easy_setopt (curl, CURLOPT_FAILONERROR, verdadero); No me importa que haya ocurrido un error, simplemente no quiero que se quede el archivo. – zombor

+0

¿Puedes actualizar tu pregunta con tu código como está ahora? – Alex

+0

Hecho. Creo que es debido a la inicial fp = fopen (outfilename.c_str(), "wb"); que crea el manejador de archivo. – zombor

1

Sé que esta es una publicación anterior, pero el error que está cometiendo es que no está verificando el valor de retorno de curl_easy_perform. Al configurar CURLOPT_FAILONERROR no se bloqueará el programa, en su lugar, se le notificará del error a través de la variable de retorno que usted denominó res. Para deshacerse del archivo vacío, podría hacer algo como esto:

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