使用libcurl显示下载进度


(1)s_get_download_file_length函数获取目标文件大小。


(2)进度条处理函数CURLOPT_PROGRESSFUNCTION,注意设置的回调函数不要忘记了正常情况下return 0;否则将会导致回调异常。











/*********************
ftp_down_load.c
**********************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//#include <curl/curl.h>
#include <curl/curl.h>

#define UserNameMaxLen 100
#define PasswordMaxLen 50
#define UrlMaxLen 1024

#define DesFileName "/share/binxu.rmvb"
#define FtpUrl "ftp://192.168.1.102/binxu.rmvb"

typedef struct ftp_init_param_s
{
	int dumy;
}ftp_init_param_t;

typedef struct ftp_connect_param_s
{
	char chUserName[UserNameMaxLen];
	char chPassword[PasswordMaxLen];
	char chUrl[UrlMaxLen];
	char chUserPwd[UserNameMaxLen+PasswordMaxLen];
}ftp_connect_param_t;

typedef struct ftp_file_s
{
  const char *pchFilename;
  FILE *stream;
  double nFileLength;
  double nCount;
  unsigned int nPersent;
}ftp_file_t;

void main_ftp_download_test();

int ftp_download(ftp_connect_param_t * pstuFtpConnectParam,ftp_file_t *pstuFtpFile);


int ftp_init(void *param);

int s_curl_init();

int s_curl_term();

double s_get_download_file_length(ftp_connect_param_t * pstuFtpConnectParam);

void set_ftp_file(ftp_file_t *pstuFtpFile, char *pchFileName);

void set_ftp_connect_param(ftp_connect_param_t * pstuFtpConnectParam);

int main()
{
	main_ftp_download_test();
	return 0;
}
void main_ftp_download_test()
{
	ftp_init_param_t pstuInitParam;
	ftp_file_t stuFtpFile;
	ftp_connect_param_t stuFtpConnectParam;
	
	memset(&pstuInitParam, 0, sizeof(ftp_init_param_t));
	if(0 != ftp_init(&pstuInitParam))
	{
		printf("\n ftp_init error \n");
		return;
	};

	memset(&stuFtpConnectParam, 0, sizeof(ftp_connect_param_t));
	set_ftp_connect_param(&stuFtpConnectParam);
	
	memset(&stuFtpFile, 0, sizeof(ftp_file_t));
	set_ftp_file(&stuFtpFile, DesFileName);

	stuFtpFile.nFileLength = s_get_download_file_length(&stuFtpConnectParam);
	if(-1 == stuFtpFile.nFileLength)
	{
		printf("\n s_get_download_file_length error \n");
		return;
	}

	printf("\n#####  file len = %lf #####\n",stuFtpFile.nFileLength);

	//int ftp_download(ftp_connect_param_t * pstuFtpConnectParam,ftp_file_t *pstuFtpFile)

    ftp_download(&stuFtpConnectParam,&stuFtpFile);

	printf("\nstuFtpFile.ncount[%lf]\n",stuFtpFile.nCount);
	if(stuFtpFile.stream)
	{ 
		fclose(stuFtpFile.stream); /* close the local file */
	}
	
	s_curl_term();
  
}

static size_t my_fwrite(void *buffer, size_t size, size_t nmemb,
                        void *stream)
{
	ftp_file_t *out = (ftp_file_t *)stream;
	static int iFlag = 0;
	static int i = 0;
	if(!out)
	{
		return -1;
	}
	//printf("\n %d \n",size*nmemb);

	if(!out->stream)
	{
		/* open file for writing */
		out->stream=fopen(out->pchFilename, "wb");
		if(!out->stream)
		{
			return -1; /* failure, can't open file to write */
		}
	}

	out->nCount += size*nmemb;
	
	return fwrite(buffer, size, nmemb, out->stream);
}

//int progress_callback(void *clientp,   double dltotal,   double dlnow,   double ultotal,   double ulnow);
int my_progress_callback(void *clientp,   double dltotal,   double dlnow,   double ultotal,   double ulnow)
{
	static int i=0;
	i++;
	if(i%10000==0 && dltotal > 0)
	{
	   //printf("\n dltotal[%03lf] dlnow[%03lf] ultotal[%03lf] ulnow[%03lf]",dltotal,dlnow,ultotal,ulnow);
		int nPersent = (int)(100.0*dlnow/dltotal);
	    printf("\n persent[%d%]",nPersent);
	}	
	return 0;
	
}

int ftp_download(ftp_connect_param_t * pstuFtpConnectParam,ftp_file_t *pstuFtpFile)
{
	CURLcode res;
	CURL *p_curl_handle = NULL;
	
	if((NULL == pstuFtpConnectParam)
		|| (NULL == pstuFtpFile)
		|| (0 == strlen(pstuFtpConnectParam->chUrl))
		|| (0 == strlen(pstuFtpConnectParam->chUserPwd)))
	{
		printf("\n param error \n");
		return -1;
	}

	p_curl_handle = curl_easy_init();

	if(NULL == p_curl_handle)
	{
		printf("\n s_get_download_file_length  if(NULL == p_curl_handle) \n");
		return -1;
	}
	/*
	* You better replace the URL with one that works! Note that we use an
	* FTP:// URL with standard explicit FTPS. You can also do FTPS:// URLs if
	* you want to do the rarer kind of transfers: implicit.
	*/
	curl_easy_setopt(p_curl_handle, CURLOPT_URL,pstuFtpConnectParam->chUrl);
	curl_easy_setopt(p_curl_handle, CURLOPT_USERPWD, pstuFtpConnectParam->chUserPwd);
	/* Define our callback to get called when there's data to be written */
	curl_easy_setopt(p_curl_handle, CURLOPT_WRITEFUNCTION, my_fwrite);
	/* Set a pointer to our struct to pass to the callback */
	curl_easy_setopt(p_curl_handle, CURLOPT_WRITEDATA, pstuFtpFile);

	//time out
	//curl_easy_setopt(curlhandle, CURLOPT_CONNECTTIMEOUT, timeout);

	curl_easy_setopt(p_curl_handle, CURLOPT_PROGRESSFUNCTION,my_progress_callback );
	curl_easy_setopt(p_curl_handle, CURLOPT_PROGRESSDATA,NULL);
	curl_easy_setopt(p_curl_handle, CURLOPT_NOPROGRESS, 0L);

	/* We activate SSL and we require it for both control and data */
	curl_easy_setopt(p_curl_handle, CURLOPT_USE_SSL, CURLUSESSL_ALL);

	/* Switch on full protocol/debug output */
	curl_easy_setopt(p_curl_handle, CURLOPT_VERBOSE, 1L);

	res = curl_easy_perform(p_curl_handle);

	/* always cleanup */
	curl_easy_cleanup(p_curl_handle);

	if(CURLE_OK == res)
	{
	    /* we success */
	    fprintf(stdout, "curl told us %d! finish!!!!!\n", res);
	}
	else
	{
	    /* we failed */
	    fprintf(stderr, "curl told us %d\n", res);
	}
	
	return 0;
}

int ftp_init(void *param)
{
	s_curl_init();
	return 0;
}

int s_curl_init()
{
	curl_global_init(CURL_GLOBAL_DEFAULT);
	return 0;
}

int s_curl_term()
{
	curl_global_cleanup();
	return 0;
}

static size_t save_header(void *ptr, size_t size, size_t nmemb, void *data)
{
    return (size_t)(size * nmemb);
}

double s_get_download_file_length(ftp_connect_param_t * pstuFtpConnectParam)
{
	double len= 0.0;
	CURL *p_curl_handle = NULL;
	CURLcode res;

	if((NULL == pstuFtpConnectParam)
		|| (0 == strlen(pstuFtpConnectParam->chUrl))
		|| (0 == strlen(pstuFtpConnectParam->chUserPwd)))
	{
		printf("\n s_get_download_file_length  param error \n");
		return -1;
	}

	p_curl_handle = curl_easy_init();

	if(NULL == p_curl_handle)
	{
		printf("\n s_get_download_file_length  if(NULL == p_curl_handle) \n");
		return -1;
	}
	
	curl_easy_setopt(p_curl_handle, CURLOPT_URL, pstuFtpConnectParam->chUrl);
	curl_easy_setopt(p_curl_handle, CURLOPT_HEADER, 1);	 //只要求header头
	curl_easy_setopt(p_curl_handle, CURLOPT_NOBODY, 1);	 //不需求body
	curl_easy_setopt(p_curl_handle, CURLOPT_HEADERFUNCTION, save_header);
	curl_easy_setopt(p_curl_handle, CURLOPT_USERPWD, pstuFtpConnectParam->chUserPwd);

	res = curl_easy_perform(p_curl_handle);
	if (res == CURLE_OK)
	{
		res= curl_easy_getinfo(p_curl_handle, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &len);
        if(CURLE_OK == res)
		{
			printf("  curl_easy_getinfo CURLE_OK !\n");
		}
		else
		{
            printf("curl_easy_getinfo failed!  res = %d\n",res);
		}
	}
	else
	{
		printf("\n s_get_download_file_length====== res = %d   \n",res);
	    len= -1;
	}

	curl_easy_cleanup(p_curl_handle);
	return len ;
}

void set_ftp_file(ftp_file_t *pstuFtpFile, char *pchFileName)
{
	if(NULL == pstuFtpFile)
	{
		printf("\n if(NULL != pstuFtpFile)  set_ftp_file \n ");
		return;
	}
	pstuFtpFile->nFileLength = 0.0;
	pstuFtpFile->pchFilename = pchFileName;
	pstuFtpFile->stream = NULL;
	pstuFtpFile->nPersent = 0;
	pstuFtpFile->nCount =0.0;
}

void set_ftp_connect_param(ftp_connect_param_t * pstuFtpConnectParam)
{
	if(NULL == pstuFtpConnectParam)
	{
		printf("\n if(NULL == pstuFtpConnectParam)  set_ftp_connect_param \n ");
		return;
	}

	memset(pstuFtpConnectParam,0,sizeof(ftp_connect_param_t));
	strncpy(pstuFtpConnectParam->chUserName,"anonymous",sizeof(pstuFtpConnectParam->chUserName)-1);

	strncpy(pstuFtpConnectParam->chPassword," ",sizeof(pstuFtpConnectParam->chPassword)-1); 
    snprintf(pstuFtpConnectParam->chUserPwd,sizeof(pstuFtpConnectParam->chUserPwd),
		"%s:%s",
		pstuFtpConnectParam->chUserName,
		pstuFtpConnectParam->chPassword);
	strncpy(pstuFtpConnectParam->chUrl,FtpUrl,sizeof(pstuFtpConnectParam->chPassword)-1);
}



  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
你可以使用libcurl库来实现下载进度的跟踪。下面是一个使用libcurl下载文件并显示进度的示例代码: ```c #include <stdio.h> #include <curl/curl.h> // 回调函数,用于跟踪下载进度 int progress_callback(void* clientp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow) { // 计算下载进度百分比 double progress = dlnow / (double)dltotal * 100.0; printf("下载进度: %.2f%%\r", progress); fflush(stdout); // 刷新输出缓冲区 return 0; } int main() { CURL* curl; CURLcode res; curl_global_init(CURL_GLOBAL_DEFAULT); curl = curl_easy_init(); if (curl) { // 设置下载地址 curl_easy_setopt(curl, CURLOPT_URL, "http://example.com/file_to_download"); // 设置进度回调函数 curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, progress_callback); curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L); res = curl_easy_perform(curl); if (res != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); curl_easy_cleanup(curl); } curl_global_cleanup(); return 0; } ``` 在上面的示例中,我们首先定义了一个名为`progress_callback`的回调函数,该函数在每个下载进度数据更新时被调用。然后,在主函数中,我们使用`curl_easy_setopt`函数设置了进度回调函数,并通过`curl_easy_perform`函数开始下载。 当你运行上述代码时,它将显示下载进度,类似于以下输出: ``` 下载进度: 50.00% ``` 你可以根据需要自定义进度显示的格式和其他操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值