c - 在 C 中使用 curl 未完成的下载

标签 c curl

我正在使用 Curl 库创建一个简单的 C 代码,使用 MSVC 从 URL 下载文件。 问题是如果连接在下载过程中中断,我的代码将卡住并且未完成的文件尚未从目录中删除。 我想要的是,如果下载失败,程序必须重试连接或删除未完成的文件,然后重试。我更喜欢使用 C 库而不是 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;
        }
    }
}

编辑--- 感谢 RingØ 的回答。我修改了代码,但我正在寻找可以恢复下载不完整文件的恢复功能。

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

最佳答案

你可以设置超时选项

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

如果30秒内没有完成操作,则触发超时。然后检查结果值,例如在 while 循环中

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

另见 the curl page .

循环示例

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

这不是理想的解决方案,如您所说,下载可能需要更多或更少的时间。如果超时足够大,这(应该)会阻止一个永无止境的程序。

众所周知,Curl 库在连接不稳定的情况下会出现一些问题 - 现在可能会有更好的东西,请尝试最新的稳定版本。

如果您在几天内没有得到更好的答案,请尝试添加 50 个 rep 的“赏金”以吸引更多关注。

关于c - 在 C 中使用 curl 未完成的下载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47483842/

相关文章:

ios - 带有 IPv6 的 iOS 中的 libcurl

xml - Linux,Curl,发送不带 xml 文件的 -X POST

c - 将多个参数传递给 C 程序

似乎无法使 C TCP 服务器-客户端通信正确

无法理解为什么 c 中的 malloc 函数会如下所述执行操作?

Bash 脚本,当我不希望 echo 换行时,它会换行

linux - 如何在 Linux 上的 Tomcat 7 上启用 SSL 并使用 curl 进行测试?

c - 打印 void 指针的字节

c - 反转 24 位颜色

api - 从 Nexus 下载神器