2017-11-25 2 views
1

Ich benutze Curl-Bibliothek, um einen einfachen C-Code mit MSVC zu erstellen, um eine Datei von einer URL herunterzuladen. Das Problem ist, wenn die Verbindung in der Mitte des Downloads bricht mein Code wird einfrieren und die unvollendete Datei wurde nicht aus dem Verzeichnis entfernt. Was ich will ist, wenn der Download fehlgeschlagen ist, muss das Programm die Verbindung erneut versuchen oder entfernen Sie die unfertige Datei und versuchen Sie es erneut. Ich bevorzuge lieber C-Bibliotheken als C++ - Bibliotheken. Hier ist der Code ich verwende:unfertigen Download mit Curl in C

//lib for curl 
#include <curl/curl.h> 
#define CURL_STATICLIB 

bool downloader3(string url, string file_path) { 
    CURL *curl; 
    FILE *fp; 
    CURLcode res; 
    curl = curl_easy_init(); 
    if (curl) { 
     fp = fopen(file_path.c_str(), "wb"); 
     curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); 
     curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data); 
     curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp); 
     res = curl_easy_perform(curl); 
     //always cleanup 
     curl_easy_cleanup(curl); 
     fclose(fp); 
     double val; 
     res = curl_easy_getinfo(curl, CURLINFO_SPEED_DOWNLOAD, &val); 
     if ((CURLE_OK == res) && (val>0)) 
      printf("Average download speed: %0.3f kbyte/sec.\n", val/1024); 
     if ((res == CURLE_OK)) { 
      printf("Download Successful!\r\n"); 
      return true; 
     } 
     else { 
      printf("Downlaod Failed!\r\n"); 
      remove(file_path.c_str()); //remove the temp file 
      return false; 
     } 
    } 
} 

EDIT --- Dank Ring Ø Antwort. Ich habe den Code geändert, aber ich suche nach einer Fortsetzungsfunktion, die den Download unvollständiger Dateien fortsetzen kann.

bool downloader3(string url, string file_path) { 
    CURL *curl; 
    FILE *fp = NULL; 
    CURLcode res; 

    int status; 
    int maxtries = 3; 
    do { 
     printf("Doing try # %d\r\n", maxtries); 
     curl = curl_easy_init(); 
     if (curl) { 
      fp = fopen(file_path.c_str(), "wb"); 
      curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); 
      curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data); 
      curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp); 
      curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10L); // 30 seconds 
      res = curl_easy_perform(curl); 
      //always cleanup 
      curl_easy_cleanup(curl); 
      fclose(fp); 
      if ((res == CURLE_OK)) { 
       printf("Download Successful!\r\n"); 
       break; 
       //return true; 
       } 
      } 
    } while (--maxtries); 
    if (maxtries) { // was OK 
     //curl_easy_cleanup(curl); // clean curl/delete file? 
     //fclose(fp); 
     return true; 
    } 
    else { 
     printf("Download Failed!\r\n"); 
     printf("file path is: %s", file_path.c_str()); 
     Sleep(5000); 
     status = remove(file_path.c_str()); //remove the unfinished file 
     if (status == 0) 
      printf("%s file deleted successfully.\n", file_path); 
     else 
     { 
      printf("Unable to delete the file\n"); 
     } 
     return false; 
    } 
} 

Antwort

1

Sie könnten ein Timeout Option

curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30L); // 30 seconds 

gesetzt, wenn die Operation nicht innerhalb von 30 Sekunden erfolgt, wird der Timeout ausgelöst. Dann überprüfen Sie den Ergebniswert, in einer while-Schleife zum Beispiel

res = curl_easy_perform(...); 
if (res == CURLE_OK) { 
    break; 
} 
// delete file 
// keep retrying (add a counter if necessary) 

Siehe auch the curl page.

Schleifen Beispiel

int maxtries = 5; 
    do { 
    curl = curl_easy_init(); 
    if (curl) { 
     ... 
     res = curl_easy_perform(...); 
     if (res == CURLE_OK) { 
      break; 
     } 

     // delete file, curl cleanup... 
     } 
    } while (--maxtries); 

    if (maxtries) { // was OK 
    // clean curl/delete file? 
    } 

Dies ist nicht die ideale Lösung, wie Sie gesagt haben, der Download mehr oder weniger Zeit kann dauern. Dies sollte (sollte) ein nie endendes Programm verhindern, vorausgesetzt, das Timeout ist groß genug.

Die Curl-Bibliothek hatte bekanntermaßen Probleme im Falle einer fehlerhaften Verbindung - es könnte heutzutage etwas Besseres geben, bitte versuchen Sie es mit dem neuesten stabilen Build.

Wenn Sie innerhalb weniger Tage keine bessere Antwort erhalten, versuchen Sie, eine "Bounty" mit 50 Wiederholungen hinzuzufügen, um mehr Aufmerksamkeit zu erhalten.

+0

Danke, aber ich weiß nicht, die genaue Zeit den Download, zum Beispiel zu beenden, wenn der Benutzer eine Datei mit 10KB/s herunterlädt es würde länger dauern. –

+0

Bitte lesen Sie die bearbeitete Antwort. –

+0

Ich habe Ihren Code versucht, aber die unfertige Datei ist immer noch da. –

0

Was Sie suchen, ist die RESUME_FROM-Funktion. Um dies zu verwenden, müssen Sie wissen, von welchem ​​Byte Sie den Download starten möchten. In diesem Beispiel ist es ein Upload, sollte aber dieselbe setopt-Technik sein. Hier ist Beispiel für die Verwendung von curl Website:

CURL *curl = curl_easy_init(); 
if(curl) { 
    curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com"); 

    /* resume upload at byte index 200 */ 
    curl_easy_setopt(curl, CURLOPT_RESUME_FROM, 200L); 

    /* ask for upload */ 
    curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); 

    /* set total data amount to expect */ 
    curl_easy_setopt(curl, CURLOPT_INFILESIZE, size_of_file); 

    /* Perform the request */ 
    curl_easy_perform(curl); 
} 

Quelle: https://curl.haxx.se/libcurl/c/CURLOPT_RESUME_FROM.html