[Network] add callBack onProcess for curl (both variant)

This commit is contained in:
Vladimir Gorshenkov
2022-01-18 15:00:27 +03:00
parent 8f9d36085b
commit 2194dd5899
4 changed files with 72 additions and 10 deletions

View File

@ -84,6 +84,16 @@ namespace NSNetwork
return written;
}
int progress_func(void* ptr, double TotalToDownload, double NowDownloaded, double TotalToUpload, double NowUploaded)
{
// It's here you will write the code for the progress message or bar
int percent = static_cast<int>((100.0 * NowDownloaded) / TotalToDownload);
if(CFileTransporterBase::m_func_onProgress)
CFileTransporterBase::m_func_onProgress(percent);
return 0;
}
static size_t write_data_to_string(char *contents, size_t size, size_t nmemb, void *userp)
{
((std::string*)userp)->append((char*)contents, size * nmemb);
@ -105,6 +115,9 @@ namespace NSNetwork
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, FALSE);
// Install the callback function
curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, progress_func);
#if defined(__linux__)
//в linux нет встроенных в систему корневых сертификатов, поэтому отключаем проверку
//http://curl.haxx.se/docs/sslcerts.html
@ -226,7 +239,7 @@ namespace NSNetwork
if (NSFile::CFileBinary::Exists(m_sDownloadFilePath))
NSFile::CFileBinary::Remove(m_sDownloadFilePath);
}
return download_external(m_sDownloadFileUrl, m_sDownloadFilePath);
return download_external(m_sDownloadFileUrl, m_sDownloadFilePath, m_func_onProgress);
}
virtual int UploadData() override
{

View File

@ -38,6 +38,9 @@
#include <unistd.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <regex>
namespace NSNetwork
{
@ -55,10 +58,9 @@ namespace NSNetwork
return url.substr(pos);
}
int download_external(const std::wstring& sUrl, const std::wstring& sOutput)
int download_external(const std::wstring& sUrl, const std::wstring& sOutput, std::function<void(int)> func_onProgress)
{
int nReturnCode = -1;
std::string sUrlA = U_TO_UTF8(sUrl);
//sUrlA =("\"" + sUrlA + "\"");
std::string sOutputA = U_TO_UTF8(sOutput);
@ -66,6 +68,9 @@ namespace NSNetwork
if (0 != nReturnCode && NSFile::CFileBinary::Exists(L"/usr/bin/curl"))
{
int pipefd[2];
pipe(pipefd);
pid_t pid = fork(); // create child process
int status;
@ -82,10 +87,11 @@ namespace NSNetwork
nargs[2] = sUrlA.c_str();
nargs[3] = "--output";
nargs[4] = sOutputA.c_str();
nargs[5] = "--silent";
nargs[6] = "-L";
nargs[7] = "--connect-timeout";
nargs[8] = "10";
//nargs[5] = "--silent";
nargs[5] = "-L";
nargs[6] = "--connect-timeout";
nargs[7] = "10";
nargs[8] = "--progress-bar";
nargs[9] = NULL;
const char* nenv[3];
@ -93,11 +99,50 @@ namespace NSNetwork
nenv[1] = "LD_LIBRARY_PATH=";
nenv[2] = NULL;
close(pipefd[0]); // close reading end in the child
dup2(pipefd[1], 1); // send stdout to the pipe
dup2(pipefd[1], 2); // send stderr to the pipe
close(pipefd[1]); // this descriptor is no longer needed
execve("/usr/bin/curl", (char * const *)nargs, (char * const *)nenv);
exit(EXIT_SUCCESS);
break;
}
default: // parent process, pid now contains the child pid
if(func_onProgress)
{
size_t size = 81;
char buffer[size];
std::string str;
close(pipefd[1]); // close the write end of the pipe in the parent
ssize_t res = 1;
while (1)
{
str.clear();
res = read(pipefd[0], buffer, sizeof(buffer));
if(res == 0)
break;
str.append(buffer);
std::regex r(R"(\d+(?:\.\d+)?%)");
std::smatch sm;
std::string percent;
std::string percentInt;
if(regex_search(str, sm, r))
{
percent = sm.str();
percentInt = percent.substr(0, percent.find("."));
func_onProgress(std::stoi(percentInt));
}
if(str.find("100.0%") != std::string::npos)
break;
}
}
while (-1 == waitpid(pid, &status, 0)); // wait for child to complete
if (WIFEXITED(status))
{