Индикатор прогресса для нескольких загрузок с cURLpp
Я пишу программу, которая загружает несколько файлов (на данный момент ее всего 2). Я пытаюсь заставить его отображать индикатор выполнения для каждой загрузки, используя ProgressFunction
Перезвоните. Проблема, с которой я сталкиваюсь, заключается в том, что я не могу найти способ разграничить прогресс между двумя файлами. Прямо сейчас это переключение между двумя. Я пытался найти какую-либо дополнительную документацию, но похоже, что ссылка на API на их сайте не работает, и есть не что иное, как некоторые основные примеры.
//ProgressCalback
double ProgressCallBack(double dltotal, double dlnow, double ultotal, double ulnow){
double progress = (dlnow/dltotal) * 100;
std::ostringstream strs;
float percent = floorf(progress * 100) / 100;
strs << percent;
printf("%s\t%d\t%d\t%d\t%d\n", strs.str().c_str(),dltotal, dlnow, ultotal, ulnow);
return 0;
};
curlpp::options::ProgressFunction progressBar(ProgressCallBack);
request1.setOpt(new curlpp::options::Url(url1));
request1.setOpt(new curlpp::options::Verbose(false));
request1.setOpt(new curlpp::options::NoProgress(0));
request1.setOpt(progressBar);
Я не совсем уверен, какая часть моего кода будет релевантной, так что вот части, относящиеся к обратному вызову прогресса. Любая помощь будет оценена.
3 ответа
Отказ от ответственности: мой C++ ржавый, и я никогда раньше не использовал curlpp, поэтому приведенный ниже код может потребовать некоторого массажа.
Что вам нужно в функции обратного вызова - это то, что может различать две загрузки. Поскольку curlpp не дает вам этого, вам, вероятно, нужно использовать функтор. Итак, для вашего обратного вызова, сделайте класс, похожий на:
class ProgressCallback
{
public:
ProgressCallback(int index) : downloadIndex(downloadIndex)
{
}
double operator()(double dltotal, double dlnow, double ultotal, double ulnow)
{
double progress = (dlnow/dltotal) * 100;
std::ostringstream strs;
float percent = floorf(progress * 100) / 100;
strs << percent;
printf("%d: %s\t%d\t%d\t%d\t%d\n", downloadIndex,
strs.str().c_str(),dltotal, dlnow, ultotal, ulnow);
return 0;
}
private:
int downloadIndex;
};
Теперь вы должны быть в состоянии использовать это как:
ProgressCallback callback1(1);
curlpp::options::ProgressFunction progressBar(callback1);
Конечно, вам нужно подумать о времени жизни этих функторов обратного вызова. Вероятно, оставлять их в стеке было бы плохой идеей.
РЕДАКТИРОВАТЬ: Кажется, есть более простой способ сделать это. в utilspp/functor.h
, определены две шаблонные функции: make_functor() и BindFirst(). Так что вы можете просто добавить downloadIndex
параметр вашего ProgressCallback
:
double ProgressCallBack(int dlIdx,
double dltotal, double dlnow,
double ultotal, double ulnow);
И зарегистрируйтесь как:
curlpp::options::ProgressFunction
progressBar(BindFirst(make_functor(ProgressCallback), 1));
Вот какая-то грязная царапина, просто чтобы выразить мысль:
class CurlppProgress
{
class Entry
{
public:
Entry( const CurlppProgress *owner );
const CurlppProgress *owner;
double dlTotal, dlNow, ulTotal, ulNow;
void callback( double dltotal, double dlnow, double ultotal, double ulnow );
};
std::vector<Entry> entries;
void print_progress() const;
friend class Entry;
public:
CurlppProgress();
void AddEntry( curlpp::Easy *request );
};
CurlppProgress::Entry::Entry( const CurlppProgress *_owner )
: owner( _owner )
, dlNow()
, dlTotal()
, ulNow()
, ulTotal()
{
}
void CurlppProgress::Entry::callback( double _dltotal, double _dlnow, double _ultotal, double _ulnow )
{
dlNow = _dlnow;
dlTotal = _dltotal;
ulNow = _ulnow;
ulTotal = _ultotal;
owner->print_progress();
}
void CurlppProgress::AddEntry( curlpp::Easy *request )
{
Entry newEntry( this );
m_entries.push_back( newEntry );
curlpp::types::ProgressFunctionFunctor progressFunctor(&m_entries.back(), &CurlppProgress::Entry::callback);
request->setOpt(new curlpp::options::ProgressFunction(progressFunctor));
}
void CurlppProgress::print_progress() const
{
double ulnow = 0.0;
double ultotal = 0.0;
double dlnow = 0.0;
double dltotal = 0.0;
for ( std::vector<Entry>::const_iterator i = entries.begin(), e = entries.end(); i != e; ++i )
{
ulnow += i->ulNow;
ulTotal += i->ulTotal;
dlnow += i->dlNow;
dltotal += i->dlTotal;
}
// print progress here
}
Но вы должны исправить это перед использованием (вещи владельца должны быть решены, а перераспределение буфера вектора вызовет сбой и так далее), но я надеюсь, что идея ясна.
Базовая библиотека libcurl позволяет передавать пользовательские данные в обратный вызов процесса через CURLOPT_PROGRESSDATA
вариант, где обратный вызов имеет дополнительный void *clientp
параметр перед double dltotal
параметр:
typedef int (*curl_progress_callback)(void *clientp,
double dltotal,
double dlnow,
double ultotal,
double ulnow);
Глядя на последний исходный код cURLpp, он не предоставляет доступ к CURLOPT_PROGRESSDATA
вариант, хотя.