代码:
#include <curl/curl.h>
#include <iostream>
#include <fstream>
#include <string>
#include <cassert>
using namespace std;
struct ImgDownloader
{
ImgDownloader(string url)
: _url(url)
{
Init();
}
~ImgDownloader()
{
clean();
}
int downloadto(string file)
{
CURLcode r = curl_easy_perform(_handle);
if(r != CURLE_OK)
{
cerr << curl_easy_strerror(r) << endl;
cout << "出错了" << endl;
return -1;
}
ofstream ofs(file);
ofs << _html_data;
return 0;
}
/*libcurl需要的回调函数,必须是纯C的,write_html变成类的成员函数以后,
编译之后,编译器会偷偷为它插入第一个入参this,可以为write_html加上static,
变成类的静态成员函数,但是,类的静态成员函数,是不允许访问类的非静态数据的
(因为非静态数据本质都是this->xxx).这样,write_html使用_html_data那一行,
编译不过去。怎么办?我们可以借助write_html最后一个入参 void*,
将this事先传过去,方法是在构造函数中,再加一行:
curl_easy_setopt(_handle, CURLOPT_WRITEDATA, static_cast<void*>(this));
然后,在write_html里,就可以再强行转换来
*/
static size_t write_html(char* data, size_t size, size_t nmemb, void* userdata)
{
assert(nmemb != 0);
//将Init()函数中传递过来this转为ImgDownloader指针
ImgDownloader* loader = static_cast <ImgDownloader*> (userdata);
loader->_html_data.append(data, size * nmemb); //html_data后附加 size*nmemb个字节的数据
return size * nmemb;
}
void Init()
{
curl_global_init(CURL_GLOBAL_DEFAULT);
_handle = curl_easy_init();
curl_easy_setopt(_handle, CURLOPT_URL, _url.c_str());
curl_easy_setopt(_handle, CURLOPT_WRITEFUNCTION, &write_html);
//将this对象传给write_html的void* userdata入参
curl_easy_setopt(_handle, CURLOPT_WRITEDATA, static_cast<void*>(this));
}
void clean()
{
curl_easy_cleanup(_handle);
curl_global_cleanup();
}
CURL* _handle;
string _url;
string _html_data;
};
int main()
{
cout << "请输入明星姓名的全拼(不要带空格或其他分隔):";
string name;
cin >> name;
string url = "http://cn.bing.com/images/search?q=" + name;
ImgDownloader downloader(url);
string file = "./data.html";
downloader.downloadto(file);
return 0;
}