1. 程式人生 > >libcurl獲取下載進度百分比,下載速度,剩餘時間

libcurl獲取下載進度百分比,下載速度,剩餘時間

如果希望獲取下載或者上傳進度相關資訊,就給CURLOPT_NOPROGRESS屬性設定0值
int ret = curl_easy_setopt(easy_handle, CURLOPT_URL, "http://speedtest.wdc01.softlayer.com/downloads/test10.zip");
ret |= curl_easy_setopt(easy_handle, CURLOPT_NOPROGRESS, 0L);

設定一個回掉函式來獲取資料

ret |= curl_easy_setopt(easy_handle, CURLOPT_XFERINFOFUNCTION, progress_callback);
progress_callback原型為
int progress_callback(void *clientp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow);
這個回撥函式可以告訴我們有多少資料需要傳輸以及傳輸了多少資料,單位是位元組。dltotal是需要下載的總位元組數,dlnow是已經下載的位元組數。ultotal是將要上傳的位元組數,ulnow是已經上傳的位元組數。如果你僅僅下載資料的話,那麼ultotal,ulnow將會是0,反之,如果你僅僅上傳的話,那麼dltotal和dlnow也會是0。clientp為使用者自定義引數,通過設定CURLOPT_XFERINFODATA屬性來傳遞。此函式返回非0值將會中斷傳輸,錯誤程式碼是CURLE_ABORTED_BY_CALLBACK

傳遞使用者自定義的引數,以CURL *easy_handle為例

ret |= curl_easy_setopt(easy_handle, CURLOPT_XFERINFODATA, easy_handle);
上面的下載可能有些問題,如果設定的URL不存在的話,伺服器返回404錯誤,但是程式發現不了錯誤,還是會下載這個404頁面。

這時需要設定CURLOPT_FAILONERROR屬性,當HTTP返回值大於等於400的時候,請求失敗

ret |= curl_easy_setopt(easy_handle, CURLOPT_FAILONERROR, 1L);
progress_callback的實現
int progress_callback(void *clientp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow)
{
	CURL *easy_handle = static_cast<CURL *>(clientp);
	char timeFormat[9] = "Unknow";

	// Defaults to bytes/second
	double speed;
	string unit = "B";

	curl_easy_getinfo(easy_handle, CURLINFO_SPEED_DOWNLOAD, &speed); // curl_get_info必須在curl_easy_perform之後呼叫

	if (speed != 0)
	{
		// Time remaining
		double leftTime = (downloadFileLength - dlnow - resumeByte) / speed;
		int hours = leftTime / 3600;
		int minutes = (leftTime - hours * 3600) / 60;
		int seconds = leftTime - hours * 3600 - minutes * 60;

#ifdef _WIN32
		sprintf_s(timeFormat, 9, "%02d:%02d:%02d", hours, minutes, seconds);
#else
		sprintf(timeFormat, "%02d:%02d:%02d", hours, minutes, seconds);
#endif
	}

	if (speed > 1024 * 1024 * 1024)
	{
		unit = "G";
		speed /= 1024 * 1024 * 1024;
	}
	else if (speed > 1024 * 1024)
	{
		unit = "M";
		speed /= 1024 * 1024;
	}
	else if (speed > 1024)
	{
		unit = "kB";
		speed /= 1024;
	}

	printf("speed:%.2f%s/s", speed, unit.c_str());

	if (dltotal != 0)
	{
		double progress = (dlnow + resumeByte) / downloadFileLength * 100;
		printf("\t%.2f%%\tRemaing time:%s\n", progress, timeFormat);
	}

	return 0;
}