关于libcurl的文章网络上很多, 这里不再描述. 以下是如何使用libcurl的例子.
一、常用函数
1) libcurl的全局初始化及释放
- CURLcode curl_global_init(long flags)
flags: CURL_GLOBAL_ALL //初始化所有的可能的调用。
CURL_GLOBAL_SSL //初始化支持 安全套接字层。
CURL_GLOBAL_WIN32 //初始化win32套接字库。
CURL_GLOBAL_NOTHING //没有额外的初始化。
- void curl_global_cleanup(void)
应该在程序开始时调用初始化函数. 虽然不调用这个初始化函数, libcurl会在curl_easy_init()函数中自动调用. 但在多线程处理时, 可能会出现多次自动调用的情况.
2) 初始化下载handle及释放
- CURL *curl = curl_easy_init();
- curl_easy_cleanup(curl);
3) 设置下载属性. 及常用参数.
- CURLcode curl_easy_setopt(CURL *handle, CURLoption option, parameter);
1. 设置下载数据的回调函数.
- option:
- CURLOPT_WRITEFUNCTION //设置回调函数
回调函数原型为: size_t function( void *ptr, size_t size, size_t nmemb, void *userp); 函数将在libcurl接收到数据后被调用。
void *ptr是下载回来的数据.
void *userp是用户指针, 用户通过这个指针传输自己的数据.
- CURLOPT_WRITEDATA
- 设置回调函数中的void *userp指针的来源。
2. 下载进度控制.
- option:
- CURLOPT_NOPROGRESS
- 为了使CURLOPT_PROGRESSFUNCTION被调用. CURLOPT_NOPROGRESS必须被设置为false.
- CURLOPT_PROGRESSFUNCTION
- CURLOPT_PROGRESSFUNCTION 指定的函数正常情况下每秒被libcurl调用一次.
- CURLOPT_PROGRESSDATA
- CURLOPT_PROGRESSDATA指定的参数将作为CURLOPT_PROGRESSFUNCTION指定函数的参数.
- 整个处理与下载数据回调的处理相同.
- 3. 其它常用属性.
option: - CURLOPT_URL
- 设置访问的URI.
- CURLOPT_NOSIGNAL
- 屏蔽其它信号.
- CURLOPT_HEADER
- 取数据时连同HTTP头部一起取回.
- CURLOPT_HEADERFUNCTION
- CURLOPT_HEADERDATA
- 只取HTTP头部数据, 处理与下载数据回调的处理相同.
- CURLOPT_TIMEOUT
- 超时时间.
- CURLOPT_CONNECTIONTIMEOUT
- 连接等待时间.
- CURLOPT_FOLLOWLOCATION
- 设置支持302重定向
- CURLOPT_RANGE
- 断点续传, 指定传输分片, 格式:"0-200"
4) 开始下载
- CURLcode curl_easy_perform(CURL *handle);
二、例程
获取网站包括HTTP头部信息在内的500字节数据.
- size_t callback_get_head(void *ptr, size_t size, size_t nmemb, void *userp)
{
strcat( userp, ptr);
return size * nmemb; //必须返回这个大小, 否则只回调一次, 不清楚为何.
}
void *get_head_thread(void *)
{
CURL *curl = curl_easy_init();
curl_easy_setopt(curl, CURLOPT_URL, "www.163.com"); //设置下载的URI
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 20); //设置超时
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); //屏蔽其它信号
curl_easy_setopt(curl, CURLOPT_HEADER, 1); //下载数据包括HTTP头部
curl_easy_setopt(curl, CURLOPT_RANGE, "0-500"); //用于断点续传, 设置下载的分片
char buffer[MAXHEADLEN] = {0x0};
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, callback_get_head); //设置下载数据的回调函数
curl_easy_setopt(curl, CURLOPT_WRITEDATA, buffer);
curl_easy_perform(curl);
curl_easy_cleanup(curl);
//此时网站HTTP头信息已经存放在buffer内.
}
struct FtpFile { std::string filename; FILE *stream; }; static size_t my_fwrite(void *buffer, size_t size, size_t nmemb, void *stream) { struct FtpFile *out=(struct FtpFile *)stream; if(out && !out->stream) { out->stream=fopen(out->filename.c_str(), "wb");//打开文件进行写入 if(!out->stream) { return -1; qDebug("&&&&&& write file %s err, open failed. \n ", out->filename.c_str()); } } return fwrite(buffer, size, nmemb, out->stream); } int Downloader::DownloadFile(string url, string filePath) { CURL *curl; CURLcode res; struct FtpFile ftpfile={ filePath, NULL }; curl = curl_easy_init(); //初始化一个curl指针 if(curl) { //设置远端地址 curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); //执行写入文件流操作 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_fwrite);//当有数据被写入,回调函数被调用, curl_easy_setopt(curl, CURLOPT_WRITEDATA, &ftpfile); //设置结构体的指针传递给回调函数 //启用时会汇报所有的信息,存放在STDERR或指定的CURLOPT_STDERR中 curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); curl_easy_setopt(curl, CURLOPT_USERPWD, "SUREN:SUREN"); //写入文件 res = curl_easy_perform(curl); //释放curl对象 curl_easy_cleanup(curl); if(res != CURLE_OK) { qDebug("&&&&&& download failed %s, url: %s \n", curl_easy_strerror(res), url.c_str()); } else { //qDebug("&&&&&& download succeed. \n"); } } if(NULL != ftpfile.stream) { //关闭文件流 fclose(ftpfile.stream); } return 0; }