1. 程式人生 > >libcurl庫實戰之下載ftp檔案並實時顯示百分比

libcurl庫實戰之下載ftp檔案並實時顯示百分比

前言

說實話,就這種東西我居然搞了快兩個小時,一開始沒有搞懂curl函式中設定的回撥函式用法以及將引數傳入回撥函式的意義,經過我查閱官網並融合官網與某些網路知識,寫出這個可以在下載時顯示下載百分比的程式碼(其實主要是網路例項不多,其實一旦看過例項,理解起來就很容易)

相關知識

下載檔案的關鍵語句:

curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, FetchFiles);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &ftpfile);

這兩句設定了下載檔案的操作,FetchFiles為回撥函式,該回調函式決定了CURLOPT_WRITEFUNCTION該做什麼操作,

&ftpfile為回撥函式的第四個引數,為回撥函式執行提供完整引數

這兩步是固定的操作,包括回撥函式的引數數量,型別都是定死的,不可以隨意修改

curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, my_progress_func);  
curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, progress_data);  

這兩句是在檔案下載時獲取檔案大小及實時下載的大小,my_progress_func為回撥函式,該函式為固定格式,所有想對實時檔案讀取有關的操作都可以寫在這裡面,包括將實時資訊展示在進度條上等

progress_data為回撥函式的引數之一,可以設定任意你需要的引數

程式碼

#include <string>
#include <iostream>
#include <fstream>
#include <stdio.h> 
#include "curl.h"
#include <stdio.h>
using namespace std;


#pragma comment(lib,"libcurl.lib")


struct FtpFile 
{
	const char *filename;
	FILE *stream;
};


static size_t FetchFiles(void *buffer, size_t size, size_t nmemb, void *stream)
{
	struct FtpFile *out = (struct FtpFile *)stream;
	if (out && !out->stream) 
	{
		// open file for writing 
		out->stream = fopen(out->filename, "wb");
		if (!out->stream)
			return -1; // failure, can't open file to write
	}
	return fwrite(buffer, size, nmemb, out->stream);
}


int my_progress_func(char *progress_data,  
					 double t, /* dltotal */  
					 double d, /* dlnow */  
					 double ultotal,  
					 double ulnow)  
{  
	printf("%s %g / %g (%g %%)\n", progress_data, d, t, d*100.0/t);  
	return 0;  
}  


int DownloadFtpFile()
{
	CURL *curl;
	CURLcode res;
	 char *progress_data = "* ";
	struct FtpFile ftpfile = {
		"E:\\vs文件\\1031CURL_TEST\\FtpDownLoad\\UltraEdit-32.rar", // name to store the file as if succesful//
		NULL         
	};
    
	curl_global_init(CURL_GLOBAL_DEFAULT);
	curl = curl_easy_init();

	if (curl) 
	{
		curl_easy_setopt(curl, CURLOPT_URL,"ftp://ljl:
[email protected]
:21/UltraEdit-32(UE)/UltraEdit-32.rar"); curl_easy_setopt(curl, CURLOPT_USERPWD, "ljl:521125"); // Define our callback to get called when there's data to be written // curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, FetchFiles); // Set a pointer to our struct to pass to the callback // curl_easy_setopt(curl, CURLOPT_WRITEDATA, &ftpfile); curl_easy_setopt(curl, CURLOPT_NOPROGRESS, FALSE); curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, my_progress_func); curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, progress_data); // Switch on full protocol/debug output // //curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); res = curl_easy_perform(curl); // always cleanup curl_easy_cleanup(curl); if (CURLE_OK != res) { //we failed fprintf(stderr, "curl told us %d\n", res); } } if (ftpfile.stream) fclose(ftpfile.stream); // close the local file curl_global_cleanup(); getchar(); return 0; } int main(void) { DownloadFtpFile(); return 0; }

後續

有些程式碼中的知識上面已經說過了,這裡說下運用libcurl的重點:curl_easy_setopt

curl_easy_setopt是全過程中最重要的一環,該函式可以多次呼叫以完成你的多個目標,而該函式的回撥函式更是重中之重!!!

下面給出curl_easy_setopt的解讀連結

執行結果

 顯示下載百分比回撥函式完全可以做更多的事,這完全取決於你的目的