Как извлечь информацию заголовка через CURLOPT_HEADERFUNCTION? - PullRequest
0 голосов
/ 29 января 2019

Я хочу извлечь информацию заголовка, используя CURLOPT_HEADERFUNCTION в моей программе на c ++.Вы можете проверить мой проект в github.https://github.com/LUCIF680/Erza-Download-Manager

Как я могу использовать CURLOPT_HEADERFUNCTION для чтения одного поля заголовка ответа? предоставляет решение о том, как получить эту информацию заголовка, но я хочу знать, почему мой код не работает ивозможное решение с примером.

//readHeader function which returns the specific header information

size_t readHeader(char* header, size_t size, size_t nitems, void *userdata) {
Erza oprations; //class which contains string function like startsWith etc
if (oprations.startsWith(header, "Content-Length:")) {
    std::string header_in_string = oprations.replaceAll(header, "Content-Length:", "");
    long size = atol(header_in_string.c_str());
    file_size = size; // file_size is global variable
    std::cout << size; // here it is showing correct file size
}
else if (oprations.startsWith(header, "Content-Type:")) {
 // do something 
}else
 // do something
return size * nitems;
}
// part of main function
curl = curl_easy_init();
    if (curl) {
        fp = fopen(path, "wb");
        curl_easy_setopt(curl, CURLOPT_URL, url);
        curl_easy_setopt(curl, CURLOPT_CAINFO, "./ca-bundle.crt");
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false);
        curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, readHeader);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
        res = curl_easy_perform(curl);
        curl_easy_cleanup(curl);

fclose(fp);
std::cout << file_size; // showing value 0

Получение правильного размера файла в функции readHeader, но получение 0 байтов в основной функции.

1 Ответ

0 голосов
/ 29 января 2019

Как показано в вашем депо github, oprations (операции!?) - локальная переменная, которая будет освобождена в конце функции readHeader.Чтобы обработать функцию readHeader и получить правильный размер файла для данного экземпляра Erza, нужно передать указатель на значение userdata.Класс Erza может быть переписан как:

class Erza : public Endeavour {

    //... your class body 

public: 
    bool download (const char *url,const char* path){
            curl = curl_easy_init();
            if (curl) {
                fp = fopen(path, "wb");
                curl_easy_setopt(curl, CURLOPT_URL, url);
                curl_easy_setopt(curl, CURLOPT_CAINFO, "./ca-bundle.crt");
                curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);
                curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false);

                curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, readHeader);
                curl_easy_setopt(curl, CURLOPT_HEADERDATA, this ); //<-- set this pointer to userdata value used in the callback.

                curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
                res = curl_easy_perform(curl);

                curl_easy_cleanup(curl);
                fclose(fp);
                return false;
            }else
                return true;

        }

    size_t analyseHeader( char* header, size_t size, size_t nitems ){

        if (startsWith(header, "Content-Length:")) {
            std::string header_in_string = replaceAll(header, "Content-Length:", "");
            long size = atol(header_in_string.c_str());
            file_size = size; // file_size is a member variable 
            std::cout << size; // here it is showing correct file size
        }
        else if (startsWith(header, "Content-Type:")) {
         // do something 
        }else
         // do something
        return size * nitems;
    }   

}//Eof class Erza

size_t readHeader(char* header, size_t size, size_t nitems, void *userdata) {

    //get the called context (Erza instance pointer set in userdata)

    Erza * oprations = (Erza *)userdata; 
    return oprations->analyseHeader( header, size, nitems );
}
...