源码:https://curl.haxx.se/
http://blog.csdn.net/vipfengxiao/article/details/6027742https://blog.csdn.net/zengraoli/article/details/11517367
https://curl.haxx.se/download/?C=M;O=D
源码下载下来后,--VS2013的编译源码方法:
编译 libcurl 步骤:打开 F:\curl-7.61.0\curl-7.61.0\winbuild\BUILD.WINDOWS.txt,依照里面的说明,打开VS2013的命令提示符,进入 F:\curl-7.61.0\curl-7.61.0\winbuild路径,然后执行 nmake /f Makefile.vc mode=dll VC=12 ENABLE_IDN=no DEBUG=no MACHINE=x64 ,然后生成 libcurl.dll libcurl.lib。
进入到 curl.exe 同级目录下面,在此目录下面的命令行中,可以执行curl命令,参见 https://blog.csdn.net/yxys01/article/details/77190619?locationNum=3&fps=1
curl的使用示例: https://curl.haxx.se/libcurl/c/example.html
下面是一些部分代码:
struct stFileInfor{
string strFileName;
int iFileSize;
string strModify;
string strFileType;//是文件夹还是文件
stFileInfor(){
strFileName = "";
iFileSize = 0;
strModify = "";
strFileType = "";
}
};
static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *stream)
{
curl_off_t nread;
size_t retcode = fread(ptr, size, nmemb, (FILE*)stream);
nread = (curl_off_t)retcode;
return retcode;
}
size_t WritedData(void *buffer, size_t size, size_t nmemb, void *userp){
int segsize = size * nmemb;
string * pstr = (string*)userp;
char* cTemp = (char *)malloc((segsize + 1)*sizeof(char));
memset(cTemp, 0, sizeof(char) * segsize + 1);
memcpy((void *)cTemp, buffer, (size_t)segsize);
(*pstr) += ((string)cTemp);
free(cTemp);
return segsize;
}
size_t DownloadCallback(void* pBuffer, size_t nSize, size_t nMemByte, void* pParam)
{
FILE* fp = (FILE*)pParam;
size_t nWrite = fwrite(pBuffer, nSize, nMemByte, fp);
return nWrite;
}
void split(string* sec, string delim, vector<string>* ret)
{
if (NULL == sec || NULL == ret)
return;
size_t last = 0;
size_t index = (*sec).find_first_of(delim, last);
while (index != string::npos){
string strSub = (*sec).substr(last, index - last);
if ("" != strSub){
ret->push_back(strSub);
}
last = index + 1;
index = (*sec).find_first_of(delim, last);
}
if (index - last > 0){
string strSub = (*sec).substr(last, index - last);
if ("" != strSub){
ret->push_back(strSub);
}
}
}
string split_getlast(std::string s, std::string delim)
{
vector<string> vecPath;
split(&s, delim, &vecPath);
for (int iIndex = (vecPath.size() - 1); iIndex >= 0; iIndex--){
if ("" != vecPath[iIndex])
return vecPath[iIndex];
}
return "";
}
string connectPath(string strPath, string strConPath)
{
string strRePath = "";
boost::filesystem::path Path = strPath;
strRePath = (Path / strConPath).string();
return strRePath;
}
void ParsFileInfor(string* strFileData, vector<stFileInfor>* ret)
{
vector<string> vecFileList;
split(strFileData, "\n", &vecFileList);
for (int iIndex = 0; iIndex < vecFileList.size(); iIndex++){
stFileInfor st;
vector<string> vecFileInfo;
split((&vecFileList[iIndex]), ";", &vecFileInfo);
for (int i = 0; i < vecFileInfo.size(); i++){
size_t index = string::npos;
//index != string::npos;
if ((index = vecFileInfo[i].find("Type")) != string::npos){
st.strFileType = vecFileInfo[i].substr(index + 5);
}
else if ((index = vecFileInfo[i].find("Size")) != string::npos){
st.iFileSize = atoi(vecFileInfo[i].substr(index + 5).c_str());
}
else if ((index = vecFileInfo[i].find("Modify")) != string::npos){
st.strModify = vecFileInfo[i].substr(index + 7);
}
else{
st.strFileName = vecFileInfo[i];
st.strFileName.erase(0, st.strFileName.find_first_not_of(" "));
st.strFileName.erase(st.strFileName.find_last_not_of(" ") + 1);
st.strFileName.erase(st.strFileName.find_last_not_of("\n") + 1);
st.strFileName.erase(st.strFileName.find_last_not_of("\r") + 1);
}
}
if ("." != st.strFileName){
ret->push_back(st);
}
}
}
string GetFilePath(string strPath)
{
bool bGet = false;
string strFilePath = "";
if (!boost::filesystem::exists(strPath)){
//bool bcreat = boost::filesystem::create_directories(strPath);
bool bcreat = boost::filesystem::create_directory(strPath);
if (bcreat)//不存在则创建目录
{
strFilePath = strPath;
}
else
strFilePath = "";
}
else{
strFilePath = strPath;
}
return strFilePath;
}
bool GetFtpFileList(char* cpAccount, char* cpPassWord, char* cpFilePath, vector<stFileInfor>* vecFileInfor, string& strError){
try{
CURL *curl;
CURLcode res;
curl = curl_easy_init();
string strReFileList = "";
if (curl) {
/* Get a file listing from sunet */
curl_easy_setopt(curl, CURLOPT_USERNAME, cpAccount);
curl_easy_setopt(curl, CURLOPT_PASSWORD, cpPassWord);
curl_easy_setopt(curl, CURLOPT_URL, cpFilePath);
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "MLSD");// MLSD\r
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WritedData);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, ((void*)&strReFileList));
res = curl_easy_perform(curl);
/* Check for errors */
if (res != CURLE_OK)
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
/* always cleanup */
curl_easy_cleanup(curl);
}
ParsFileInfor(&strReFileList, vecFileInfor);
return true;
}
catch (exception &e){
strError = "Exception Occurs :" + string(e.what());
return false;
}
}
bool DownloadFtpFile(char* cpAccount, char* cpPassWord, char* cpUrlDownloadAddress, char* cpPath, string& strError)
{
try{
bool bResult = false;
//初始化curl,这个是必须的
CURL *curl = curl_easy_init();
curl_easy_setopt(curl, CURLOPT_URL, cpUrlDownloadAddress);
string strFileName = cpPath;
if ("" == strFileName){
strFileName = split_getlast(cpUrlDownloadAddress, "\/");
if ("" == strFileName){
strFileName = split_getlast(cpUrlDownloadAddress, "\\");
}
}
//设置接收数据的回调
FILE* file = fopen(const_cast<char*>(strFileName.c_str()), "wb");
if (NULL == curl || NULL == file){
strError = "fileopen erro: " + string(cpPath);
return false;
}
curl_easy_setopt(curl, CURLOPT_USERNAME, cpAccount);
curl_easy_setopt(curl, CURLOPT_PASSWORD, cpPassWord);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, DownloadCallback);
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 15);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, file);
curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 5);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, true);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, FALSE);
CURLcode retcCode = curl_easy_perform(curl);
fclose(file);
if (retcCode != CURLE_OK){
strError = "download failure URL= " + string(cpUrlDownloadAddress) + ";reason = " + curl_easy_strerror(retcCode);
}
else{
long responseCode = 0;
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &responseCode);
struct _stat info;
_stat(cpPath, &info);
//int size = info.st_size;
if ((200 <= responseCode) &&
responseCode < 300){
bResult = true;
}
else if (responseCode < 200 || responseCode >= 300){
strError = "download failure URL= " + string(cpUrlDownloadAddress) + ";reason = " + curl_easy_strerror(retcCode);
bResult = false;
}
}
//清理curl,和前面的初始化匹配
curl_easy_cleanup(curl);
return bResult;
}
catch (exception &e){
strError = "Exception Occurs :" + string(e.what());
return false;
}
}
bool DownloadFtpFolder(char* cpAccount, char* cpPassWord, char* cpUrlDownloadAddress, char* cpPath, string& strError){
try{
string strFoldName = split_getlast(cpUrlDownloadAddress, "\/");
if ("" == strFoldName){
strFoldName = split_getlast(cpUrlDownloadAddress, "\\");
}
string strTarFile = connectPath(cpPath, strFoldName);
strTarFile = GetFilePath(strTarFile);
vector<stFileInfor> vecFileList;
GetFtpFileList(cpAccount, cpPassWord, cpUrlDownloadAddress, &vecFileList, strError);
for (int i = 0; i < vecFileList.size(); i++){
if (vecFileList[i].strFileType == "dir"){
string strUrlDownloadAddress = cpUrlDownloadAddress;
strUrlDownloadAddress = strUrlDownloadAddress + vecFileList[i].strFileName + "\/";
DownloadFtpFolder(cpAccount, cpPassWord, const_cast<char*>(strUrlDownloadAddress.c_str()), const_cast<char*>(strTarFile.c_str()), strError);
}
else if (vecFileList[i].strFileType == "file"){
string strUrlDownloadAddress = cpUrlDownloadAddress;
strUrlDownloadAddress += vecFileList[i].strFileName;
string strTarFileTemp = connectPath(strTarFile, vecFileList[i].strFileName);
DownloadFtpFile(cpAccount, cpPassWord, const_cast<char*>(strUrlDownloadAddress.c_str()), const_cast<char*>(strTarFileTemp.c_str()), strError);
}
}
return true;
}
catch (exception &e){
strError = "Exception Occurs :" + string(e.what());
return false;
}
}
bool UpFtpFile(char* cpAccount, char* cpPassWord, char* cpUrl, char* cpPath, string& strError)
{
try
{
CURL *curl;
CURLcode res;
FILE *hd_src;
struct stat file_info;
curl_off_t fsize;
struct curl_slist *headerlist = NULL;
if (stat(cpPath, &file_info)) {
strError = string(cpPath) + " open erro ;reason = " + strerror(errno);
return false;
}
fsize = (curl_off_t)file_info.st_size;
/* get a FILE * of the same file */
hd_src = fopen(cpPath, "rb");
/* In windows, this will init the winsock stuff */
curl_global_init(CURL_GLOBAL_ALL);
/* get a curl handle */
curl = curl_easy_init();
if (curl) {
/* we want to use our own read function */
curl_easy_setopt(curl, CURLOPT_USERNAME, cpAccount);
curl_easy_setopt(curl, CURLOPT_PASSWORD, cpPassWord);
curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_callback);
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
curl_easy_setopt(curl, CURLOPT_URL, cpUrl);
curl_easy_setopt(curl, CURLOPT_READDATA, hd_src);
curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)fsize);
res = curl_easy_perform(curl);
if (res != CURLE_OK){
strError = "up failure; filename = " + string(cpPath) + "; URL = " + string(cpUrl) + "; reason = " + curl_easy_strerror(res);
}
/* always cleanup */
curl_easy_cleanup(curl);
}
fclose(hd_src); /* close the local file */
curl_global_cleanup();
return (res == CURLE_OK);
}
catch (exception &e){
strError = "Exception Occurs :" + string(e.what());
return false;
}
}