операция была прервана обратным вызовом приложения - libcurl - PullRequest
0 голосов
/ 06 марта 2020

У меня есть следующая программа libcurl. Когда я запускаю программу, я получаю следующую ошибку:

Operation was aborted by an application callback

Process finished with exit code 42

Моя полная программа

#include <stdio.h>
#include <curl/curl.h>
#include <cstdint>
#include <malloc.h>
#include <cstring>

#define TIMETYPE double
#define TIMEOPT CURLINFO_TOTAL_TIME

#define STOP_DOWNLOAD_AFTER_THIS_MANY_BYTES         6000

struct myprogress {
    TIMETYPE lastruntime; 
    CURL *curl;
};

struct memoryStruct {
    uint8_t* memory;
    size_t size;
};

size_t handleData(void* contents, size_t size, size_t nmemb, void* stream) {
    size_t realSize = size * nmemb;
    struct memoryStruct* mem = static_cast<struct memoryStruct*>(stream);

    mem->memory = static_cast<uint8_t*>(realloc(mem->memory, (mem->size + realSize + 1)));
    if (mem->memory == nullptr) {
        return 0;
    }
    memcpy(&(mem->memory[mem->size]), contents, realSize);
    mem->size += realSize;
    mem->memory[mem->size] = 0;

    return realSize;
}

static int xferinfo(void *p,
                    curl_off_t dltotal, curl_off_t dlnow,
                    curl_off_t ultotal, curl_off_t ulnow)
{
    struct myprogress *myp = (struct myprogress *)p;
    CURL *curl = myp->curl;
    TIMETYPE curtime = 0;

    curl_easy_getinfo(curl, TIMEOPT, &curtime);

    myp->lastruntime = curtime;
    fprintf(stderr, "TOTAL TIME: %f \r\n", curtime);

    fprintf(stderr,"  DOWN: %" CURL_FORMAT_CURL_OFF_T " of %" CURL_FORMAT_CURL_OFF_T
                    "\r\n", dlnow, dltotal);

    if(dlnow > STOP_DOWNLOAD_AFTER_THIS_MANY_BYTES)
        return 1;
    return 0;
}

int main(void)
{
    CURL *curl;
    CURLcode res = CURLE_OK;
    struct myprogress prog;
    struct memoryStruct m_chunk;

    curl = curl_easy_init();
    if(curl) {
        prog.lastruntime = 0;
        prog.curl = curl;

        m_chunk.memory = static_cast<uint8_t*>(malloc(1));
        if (nullptr == m_chunk.memory) {
            return 1;
        }
        m_chunk.size = 0;


        curl_easy_setopt(curl, CURLOPT_URL, "http://172.16.132.84:5000/download/file.out");

        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, handleData);

        curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void*) &m_chunk);

        curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, xferinfo);

        curl_easy_setopt(curl, CURLOPT_XFERINFODATA, &prog);

        curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);
        res = curl_easy_perform(curl);

        if(res != CURLE_OK) {
            fprintf(stderr, "%s\n", curl_easy_strerror(res));
        }
        curl_easy_cleanup(curl);
    }
    return (int)res;
}

1 Ответ

3 голосов
/ 06 марта 2020

Ваш файл больше 6000 байтов:

STOP_DOWNLOAD_AFTER_THIS_MANY_BYTES         6000

В этом случае вы возвращаете 1 в функции xferinfo, которая прерывает загрузку.

Документация

Если ваша функция обратного вызова возвращает CURL_PROGRESSFUNC_CONTINUE, это заставит libcurl продолжить выполнение функции прогресса по умолчанию.

Возвращение любого другого ненулевого значения из этого обратного вызова приведет к тому, что libcurl прервет передачу и return CURLE_ABORTED_BY_CALLBACK.

см. https://curl.haxx.se/libcurl/c/CURLOPT_XFERINFOFUNCTION.html

Тест

Если я загружаю файл с вашим кодом с 4431 байт я получаю в консоли отладки:

...
TOTAL TIME: 0.088631 
DOWN: 4431 of 4431

Process finished with exit code 0

Если я изменю STOP_DOWNLOAD_AFTER_THIS_MANY_BYTES на 2000, то получу:

... 
Operation was aborted by an application callback

Process finished with exit code 42
...