概要
libcurl 是一个开源的多协议文件传输库,它提供了强大的功能,用于通过各种网络协议实现数据传输。它是 C 库,支持 HTTP、HTTPS、FTP 等多种协议,广泛应用于 Web 客户端、爬虫、文件下载等场景。
使用流程
这里提供一个编译好的 libcurl 库,需要的可以直接点击下载。首先,首先工程属性配置好头文件和库文件位置:
可以注意到,这里除了引进库本身的 libcurld.lib 之外,还引入了 ws2_32.lib、crypt32.lib、wldap32.lib 和 normaliz.lib,这些额外的库是 libcurl 的依赖库,它们提供了不同的网络和加密功能。如果不链接这些库,链接器找不到相应的函数实现,会导致“无法解析的外部符号”错误。此外,预处理器需要添加 CURL_STATICLIB:
也可以在代码中包含 curl 头文件之前定义该宏:
#define CURL_STATICLIB
#include <curl/curl.h>
如果不加,编译会报错“无法解析的外部符号”。原因是,默认情况下 libcurl 的头文件会将所有API函数声明为 __declspec(dllimport),这意味着编译器会期望从 DLL 动态库中导入这些函数。当你使用的是静态库(.lib)而不是 DLL 时,这些函数实际上是直接链接到你的程序中,而不是从DLL导入,此时 __declspec(dllimport) 的声明就会导致链接错误。定义 CURL_STATICLIB 宏会使 curl 头文件中的 API 声明不包含 __declspec(dllimport),从而允许正确链接静态库。下面提供一段使用 libcurl 库从服务器下载文件的代码:
#include <iostream>
#include <fstream>
#include <sstream>
#include <chrono>
#include <io.h>
#include <curl/curl.h>
static size_t WriteCallback(void *contents, size_t size, size_t nmemb, void *userp) {
std::ofstream *outFile = (std::ofstream*)userp;
size_t totalSize = size * nmemb;
outFile->write((char*)contents, totalSize);
return totalSize;
}
bool DownloadFile(string url, string fileName) {
bool ret = false;
if (curl_global_init(CURL_GLOBAL_DEFAULT) != CURLE_OK) {
return ret;
}
CURL *pCurl = curl_easy_init();
if (!pCurl) {
curl_global_cleanup();
return ret;
}
std::ofstream outFile(fileName.c_str(), std::ios::binary);
if (!outFile.is_open()) {
curl_easy_cleanup(pCurl);
pCurl = nullptr;
curl_global_cleanup();
return ret;
}
curl_easy_setopt(pCurl, CURLOPT_URL, url.c_str());
curl_easy_setopt(pCurl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(pCurl, CURLOPT_WRITEDATA, &outFile);
if (curl_easy_perform(pCurl) == CURLE_OK) {
long http_code = 0;
curl_easy_getinfo(pCurl, CURLINFO_RESPONSE_CODE, &http_code);
if (http_code == 200) {
ret = true;
}
}
curl_easy_cleanup(pCurl);
pCurl = nullptr;
curl_global_cleanup();
outFile.close();
return ret;
}
int main() {
DownloadFile("http://test.cn/my.txt", "D:\\download.txt");
return 0;
}