curl/libcurl 下载及编译
下载源码
github 地址 : https://github.com/curl/curl
。
Release 版本下载地址: https://github.com/curl/curl/releases/
。
下载 “curl-8.0.1.zip” 包,并解压:
打开 projects/Windows
目录下对应 VS
的工程文件,比如我打开的是 VC14.10
的。
源码编译
用 VS2019
打开工程,然后设置工程参数。
C/C++设置
预处理器选项中,将USE_LIBSSH、USE_LIBSSH2
等宏去掉。
链接器
在输入选项中,将libssl.lib
相关的依赖都取消掉。
生成库
MFC示例项目
MFC项目配置
添加头文件包含:
设置预处理器:
设置链接器:
设置依赖库:
MFC源码
/*------------------------------------------------------------------
* 官方示例代码,移植过来
*-----------------------------------------------------------------*/
//---- common progress display ---- //
struct CustomProgress
{
curl_off_t lastruntime; /* type depends on version, see above */
CURL* curl;
};
//---- upload related ---- //
//parse headers for Content-Length
size_t getContentLengthFunc(void* ptr, size_t size, size_t nmemb, void* stream)
{
int r;
long len = 0;
r = sscanf((const char*)ptr, "Content-Length: %ld\n", &len);
if (r) /* Microsoft: we don't read the specs */
*((long*)stream) = len;
return size * nmemb;
}
//discard already downloaded data
size_t discardFunc(void* ptr, size_t size, size_t nmemb, void* stream)
{
return size * nmemb;
}
//read data to upload
size_t readfunc(void* ptr, size_t size, size_t nmemb, void* stream)
{
FILE* f = (FILE*)stream;
size_t n;
if (ferror(f))
return CURL_READFUNC_ABORT;
n = fread(ptr, size, nmemb, f) * size;
return n;
}
//do upload, will overwrite existing file
int FtpUpload(const char* remote_file_path,
const char* local_file_path,
const char* username,
const char* password,
long timeout, long tries = 3)
{
//init curl handle
curl_global_init(CURL_GLOBAL_ALL);
CURL* curlhandle = curl_easy_init();
//get user_key pair
char user_key[1024] = { 0 };
sprintf(user_key, "%s:%s", username, password);
FILE* file;
long uploaded_len = 0;
CURLcode ret = CURLE_GOT_NOTHING;
file = fopen(local_file_path, "rb");
if (file == NULL)
{
perror(NULL);
return 0;
}
//使能上传功能
curl_easy_setopt(curlhandle, CURLOPT_UPLOAD, 1L);
curl_easy_setopt(curlhandle, CURLOPT_URL, remote_file_path);
curl_easy_setopt(curlhandle, CURLOPT_USERPWD, user_key);
if (timeout) {
curl_easy_setopt(curlhandle, CURLOPT_FTP_RESPONSE_TIMEOUT, timeout);
}
curl_easy_setopt(curlhandle, CURLOPT_HEADERFUNCTION, getContentLengthFunc);
curl_easy_setopt(curlhandle, CURLOPT_HEADERDATA, &uploaded_len);
curl_easy_setopt(curlhandle, CURLOPT_WRITEFUNCTION, discardFunc);
curl_easy_setopt(curlhandle, CURLOPT_READFUNCTION, readfunc);
curl_easy_setopt(curlhandle, CURLOPT_READDATA, file);
curl_easy_setopt(curlhandle, CURLOPT_FTPPORT, "-"); /* disable passive mode */
curl_easy_setopt(curlhandle, CURLOPT_FTP_CREATE_MISSING_DIRS, 1L);
// upload: 断点续传
for (int c = 0; (ret != CURLE_OK) && (c < tries); c++)
{
/* are we resuming? */
if (c)
{ /* yes */
/* determine the length of the file already written */
/*
* With NOBODY and NOHEADER, libcurl will issue a SIZE
* command, but the only way to retrieve the result is
* to parse the returned Content-Length header. Thus,
* getContentLengthfunc(). We need discardfunc() above
* because HEADER will dump the headers to stdout
* without it.
*/
curl_easy_setopt(curlhandle, CURLOPT_NOBODY, 1L);
curl_easy_setopt(curlhandle, CURLOPT_HEADER, 1L);
ret = curl_easy_perform(curlhandle);
if (ret != CURLE_OK)
continue;
curl_easy_setopt(curlhandle, CURLOPT_NOBODY, 0L);
curl_easy_setopt(curlhandle, CURLOPT_HEADER, 0L);
fseek(file, uploaded_len, SEEK_SET);
curl_easy_setopt(curlhandle, CURLOPT_APPEND, 1L);
}
else
curl_easy_setopt(curlhandle, CURLOPT_APPEND, 0L);
ret = curl_easy_perform(curlhandle);
}
fclose(file);
int curl_state = 0;
if (ret == CURLE_OK)
{
curl_state = 1;
}
else
{
fprintf(stderr, "%s\n", curl_easy_strerror(ret));
curl_state = 0;
}
//推出
curl_easy_cleanup(curlhandle);
curl_global_cleanup();
return curl_state;
}
/*------------------------------------------------------------------
* MFC对话框调用接口示例
*-----------------------------------------------------------------*/
//MFC对话框《确定》按钮槽函数
void CLibcurlftpcliDlg::OnBnClickedOk()
{
//TODO: 通过libcurl远程获取FTP服务器上的PlanPath-0911.xml文件
//FTP远程文件位置及服务器IP地址
std::string strRemoteFilePath = "ftp://192.168.32.165:21/myfile/PlanPath-0911.xml";
//本地存放路径
std::string strLocalFilePath = "C:/Users/MG/Desktop/AC/tongji/xmlconfig/PlanPath-0911.xml";
//获取文件
int iRet = FtpUpload(strRemoteFilePath.c_str(), strLocalFilePath.c_str(), "root", "root123", 1);
}