.h
static bool curlDownloadFile(const std::string &remotepath,
const std::string &localpath,
ProgressData &progressdata,
downloadProgressCallBack cb = NULL,
LoadType type = HTTP,
char* user_pwd = NULL,
char *port = NULL,
bool resume = false,
long timeout = 5,
long tries = 3);
.cpp
int defaultDownloadProgressFunc(char *progress_data,
double dltotal,double dlnow,
double ultotal,double ulnow)
{
ProgressData* pd = (ProgressData*)progress_data;
pd->ret.dresult.dlnow = dlnow;
pd->ret.dresult.dltotal = dltotal;
if(!(dltotal - 0.0))
pd->ret.dresult.downloadgdrate = (dlnow)*100.0/( dltotal);
else
pd->ret.dresult.downloadgdrate = 0.0;
std::cout << dlnow << "<--->" << dltotal << std::endl;
return 0;
}
#if 0
//阻塞型下载
bool curlDownloadFile(const std::string& remotepath,
const std::string& localpath,
ProgressData& progressdata,
downloadProgressCallBack cb, /*progress callback function*/
LoadType type,char* user_pwd,char *port,
bool resume, long timeout , long tries )
{
// 文件名包含中文会导致文件下载失败
// printf("%s %d : %s %s \n",__FUNCTION__,__LINE__,localpath,remotepath);
std::cout << __FUNCTION__ <<__LINE__ << " " << remotepath << " " << localpath << std::endl;
CURL *curlhandle = NULL;
// curl_global_init(CURL_GLOBAL_ALL);
curlhandle = curl_easy_init();
if(!curlhandle){ return false; }
FILE *f;
long filesize =0 ;
CURLcode r = CURLE_GOT_NOTHING;
struct myprogress prog;
char *progress_data = (char*) &prog;
long intiSize = 0;
FILE *file = fopen(localpath.c_str(),"wb");
if(!file){
perror(" open failed.\n");
return r;
}
intiSize = filelength(fileno(file));
fclose(file);
prog.local_file_len = intiSize;
// if( prog.local_file_len > 0) resume = 1;
f = fopen(localpath.c_str(), "ab+");
if ( NULL == f ) {
perror(NULL);
return false;
}
/// 解决传参中包含中文乱码的问题
using namespace TiangongCloud;
QString remotePathQstring = str2qstr(remotepath);
QStringList lst = remotePathQstring.split("/");
lst.removeLast();
QString rFileName = lst.last();
QFileInfo info(remotePathQstring);
QString _baseName = info.baseName();
QString _surfix = info.suffix();
qDebug() << __FUNCTION__ << __LINE__ << _baseName << _surfix;
/// basename可能是中文,必须转码
QString prePath = lst.join("/");
string param;
char * escape_control = curl_escape(_baseName.toStdString().c_str(), _baseName.length());
param = string(escape_control);
curl_free(escape_control);
// %E8%BD%B4-PMI.par
// %D6%E1-PM.par
// string dlurl = qstr2str(prePath) + "/" + param + + "." + _surfix.toStdString() + rFileName.toStdString();
// std::cout << __FUNCTION__ <<__LINE__ << " " << dlurl << std::endl;
// curl_easy_setopt(curlhandle, CURLOPT_URL, remotepath );
curl_easy_setopt(curlhandle, CURLOPT_URL, string(string_To_UTF8(remotepath)).c_str() );
std::cout << "++++++++++++++++++ " << __FUNCTION__ << " " << __LINE__ << " "
<< remotepath << " " << string_To_UTF8(remotepath) << std::endl;
if(timeout)
curl_easy_setopt(curlhandle, CURLOPT_CONNECTTIMEOUT, timeout);
curl_easy_setopt(curlhandle, CURLOPT_HEADERFUNCTION, &sdkcommucation::getcontentlengthfunc);
curl_easy_setopt(curlhandle, CURLOPT_HEADERDATA, &filesize);
curl_easy_setopt(curlhandle, CURLOPT_RESUME_FROM_LARGE, resume ? prog.local_file_len : 0);
curl_easy_setopt(curlhandle, CURLOPT_WRITEDATA, f);
curl_easy_setopt(curlhandle, CURLOPT_WRITEFUNCTION, &sdkcommucation::write_data);
if(cb)
curl_easy_setopt(curlhandle, CURLOPT_PROGRESSFUNCTION, cb);
else
curl_easy_setopt(curlhandle, CURLOPT_PROGRESSFUNCTION, defaultDownloadProgressFunc);
curl_easy_setopt(curlhandle, CURLOPT_PROGRESSDATA, &progressdata);
if(FTP == type){
/* "name:password" to use when fetching. */
curl_easy_setopt(curlhandle, CURLOPT_USERPWD, user_pwd);
curl_easy_setopt(curlhandle, CURLOPT_FTPPORT,port ? port : "-");
curl_easy_setopt(curlhandle, CURLOPT_FTP_CREATE_MISSING_DIRS, 0L);
}
curl_easy_setopt(curlhandle, CURLOPT_SSL_VERIFYPEER, 0);
curl_easy_setopt(curlhandle, CURLOPT_SSL_VERIFYHOST, 0);
curl_easy_setopt(curlhandle, CURLOPT_NOPROGRESS, 0L);
curl_easy_setopt(curlhandle, CURLOPT_VERBOSE, 1L);
for(int c = 0; (r != CURLE_OK) && (c < tries); c++) {
r = curl_easy_perform(curlhandle);
}
if (r != CURLE_OK){
fprintf(stderr, "==> %s\n", curl_easy_strerror(r));
}
fclose(f);
curl_easy_cleanup(curlhandle);
curl_global_cleanup();
return r == CURLE_OK;
}
#else //非阻塞型下载
bool curlDownloadFile(const std::string& remotepath,
const std::string& localpath,
ProgressData& progressdata,
downloadProgressCallBack cb, /*progress callback function*/
LoadType type,char* user_pwd,char *port,
bool resume, long timeout , long tries )
{
// 文件名包含中文会导致文件下载失败
// printf("%s %d : %s %s \n",__FUNCTION__,__LINE__,localpath,remotepath);
std::cout << __FUNCTION__ <<__LINE__ << " " << remotepath << " " << localpath << std::endl;
CURL *curlhandle = NULL;
// curl_global_init(CURL_GLOBAL_ALL);
CURLM *multi_handle;
int still_running = 0; /* keep number of running handles */
int repeats = 0;
curl_global_init(CURL_GLOBAL_DEFAULT);
curlhandle = curl_easy_init();
if(!curlhandle){ return false; }
multi_handle = curl_multi_init();
if(!multi_handle){ return false; }
/* add the individual transfers */
curl_multi_add_handle(multi_handle, curlhandle);
FILE *f;
long filesize =0 ;
CURLMcode r = CURLM_CALL_MULTI_PERFORM;
struct myprogress prog;
char *progress_data = (char*) &prog;
long intiSize = 0;
FILE *file = fopen(localpath.c_str(),"wb");
if(!file){
perror(" open failed.\n");
return r;
}
intiSize = filelength(fileno(file));
fclose(file);
prog.local_file_len = intiSize;
// if( prog.local_file_len > 0) resume = 1;
f = fopen(localpath.c_str(), "ab+");
if ( NULL == f ) {
perror(NULL);
return false;
}
/// 解决传参中包含中文乱码的问题
using namespace TiangongCloud;
QString remotePathQstring = str2qstr(remotepath);
QStringList lst = remotePathQstring.split("/");
lst.removeLast();
QString rFileName = lst.last();
QFileInfo info(remotePathQstring);
QString _baseName = info.baseName();
QString _surfix = info.suffix();
qDebug() << __FUNCTION__ << __LINE__ << _baseName << _surfix;
/// basename可能是中文,必须转码
QString prePath = lst.join("/");
string param;
char * escape_control = curl_escape(_baseName.toStdString().c_str(), _baseName.length());
param = string(escape_control);
curl_free(escape_control);
// %E8%BD%B4-PMI.par
// %D6%E1-PM.par
// string dlurl = qstr2str(prePath) + "/" + param + + "." + _surfix.toStdString() + rFileName.toStdString();
// std::cout << __FUNCTION__ <<__LINE__ << " " << dlurl << std::endl;
// curl_easy_setopt(curlhandle, CURLOPT_URL, remotepath );
UTool tool;
curl_easy_setopt(curlhandle, CURLOPT_URL, string(string_To_UTF8(tool.urlcode(remotepath))).c_str() );
std::cout << "++++++++++++++++++ " << __FUNCTION__ << " " << __LINE__ << " "
<< remotepath << " " << string_To_UTF8(tool.urlcode(remotepath)) << std::endl;
if(timeout)
curl_easy_setopt(curlhandle, CURLOPT_CONNECTTIMEOUT, timeout);
curl_easy_setopt(curlhandle, CURLOPT_HEADERFUNCTION, &sdkcommucation::getcontentlengthfunc);
curl_easy_setopt(curlhandle, CURLOPT_HEADERDATA, &filesize);
curl_easy_setopt(curlhandle, CURLOPT_RESUME_FROM_LARGE, resume ? prog.local_file_len : 0);
curl_easy_setopt(curlhandle, CURLOPT_WRITEDATA, f);
curl_easy_setopt(curlhandle, CURLOPT_WRITEFUNCTION, &sdkcommucation::write_data);
if(cb)
curl_easy_setopt(curlhandle, CURLOPT_PROGRESSFUNCTION, cb);
else
curl_easy_setopt(curlhandle, CURLOPT_PROGRESSFUNCTION, defaultDownloadProgressFunc);
curl_easy_setopt(curlhandle, CURLOPT_PROGRESSDATA, &progressdata);
if(FTP == type){
/* "name:password" to use when fetching. */
curl_easy_setopt(curlhandle, CURLOPT_USERPWD, user_pwd);
curl_easy_setopt(curlhandle, CURLOPT_FTPPORT,port ? port : "-");
curl_easy_setopt(curlhandle, CURLOPT_FTP_CREATE_MISSING_DIRS, 0L);
}
curl_easy_setopt(curlhandle, CURLOPT_SSL_VERIFYPEER, 0);
curl_easy_setopt(curlhandle, CURLOPT_SSL_VERIFYHOST, 0);
curl_easy_setopt(curlhandle, CURLOPT_NOPROGRESS, 0L);
curl_easy_setopt(curlhandle, CURLOPT_VERBOSE, 1L);
/* we start some action by calling perform right away */
r = curl_multi_perform(multi_handle, &still_running);
while(still_running) {
int numfds;
/* wait for activity, timeout or "nothing" */
r = curl_multi_wait(multi_handle, NULL, 0, 1000, &numfds);
if(r != CURLM_OK) {
r = CURLM_BAD_EASY_HANDLE;
fprintf(stderr, "curl_multi_wait() failed, code %d.\n", r);
break;
}
/* 'numfds' being zero means either a timeout or no file descriptors to
wait for. Try timeout on first occurrence, then assume no file
descriptors and no file descriptors to wait for means wait for 100
milliseconds. */
if(!numfds) {
repeats++; /* count number of repeated zero numfds */
if(repeats > 1) {
WAITMS(100); /* sleep 100 milliseconds */
}
}
else
repeats = 0;
if (repeats > 30) //30s重连
{
r = CURLM_BAD_EASY_HANDLE;
fprintf(stderr, "netwoek is error:%d", r);
break;
}
r = curl_multi_perform(multi_handle, &still_running);
}
curl_multi_remove_handle(multi_handle, curlhandle);
curl_easy_cleanup(curlhandle);
curl_multi_cleanup(multi_handle);
curl_global_cleanup();
fclose(f);
return r == CURLE_OK;
}
#endif