libcurl常用方法 post get download

GET

::curl_easy_setopt(curl_, CURLOPT_URL, final_url.c_str());
::curl_easy_setopt(curl_, CURLOPT_HTTPGET, 1);
::curl_easy_setopt(curl_, CURLOPT_HEADER, with_header);
if (!vHeader.empty())
{
	struct curl_slist* headers = NULL;
	for (int i = 0; i < vHeader.size();++i)
	{
		headers = curl_slist_append(headers, vHeader[i].c_str());
	}
	curl_easy_setopt(curl_, CURLOPT_HTTPHEADER, headers);
}
::curl_easy_setopt(curl_, CURLOPT_TIMEOUT, timeout);
::curl_easy_setopt(curl_, CURLOPT_WRITEFUNCTION, WriteCallback4Http);
::curl_easy_setopt(curl_, CURLOPT_WRITEDATA, (void*) &rsp);
::curl_easy_setopt(curl_, CURLOPT_NOSIGNAL, 1);
::curl_easy_perform(curl_);
//暂时不考虑重定向

POST

::curl_easy_reset(curl_);

::curl_easy_setopt(curl_, CURLOPT_URL, url.c_str());
::curl_easy_setopt(curl_, CURLOPT_POST, 1);
::curl_easy_setopt(curl_, CURLOPT_HEADER, with_header);
//构建HTTP报文头
if (!vHeader.empty())
{
	struct curl_slist* headers = NULL;
	for (int i = 0; i < vHeader.size();++i)
	{
		headers = curl_slist_append(headers, vHeader[i].c_str());
	}
	curl_easy_setopt(curl_, CURLOPT_HTTPHEADER, headers);
}
::curl_easy_setopt(curl_, CURLOPT_POSTFIELDS, data);
::curl_easy_setopt(curl_, CURLOPT_POSTFIELDSIZE, data_len);
::curl_easy_setopt(curl_, CURLOPT_TIMEOUT, timeout);
::curl_easy_setopt(curl_, CURLOPT_WRITEFUNCTION, WriteCallback4Http);
::curl_easy_setopt(curl_, CURLOPT_WRITEDATA, (void*) &rsp);
::curl_easy_setopt(curl_, CURLOPT_SSL_VERIFYPEER, 0L);
::curl_easy_setopt(curl_, CURLOPT_SSL_VERIFYHOST, 0L);
::curl_easy_setopt(curl_, CURLOPT_NOSIGNAL, 1);
::curl_easy_perform(curl_);
//暂时不考虑重定向

HEAD

::curl_easy_setopt(curl_,CURLOPT_NOBODY,1L);

DOWNLOAD

::curl_easy_setopt(curl_, CURLOPT_URL, url.c_str());
::curl_easy_setopt(curl_, CURLOPT_HTTPGET, 1L);
::curl_easy_setopt(curl_, CURLOPT_CONNECTTIMEOUT, 300L);
::curl_easy_setopt(curl_, CURLOPT_LOW_SPEED_TIME, 1800L);
::curl_easy_setopt(curl_, CURLOPT_LOW_SPEED_LIMIT, 10L);
::curl_easy_setopt(curl_, CURLOPT_USERAGENT, CURL_USER_AGENT);
::curl_easy_setopt(curl_, CURLOPT_SSL_VERIFYPEER, 0L);
::curl_easy_setopt(curl_, CURLOPT_SSL_VERIFYHOST, 0L);
::curl_easy_setopt(curl_, CURLOPT_NOSIGNAL, 1L);

//写回调
::curl_easy_setopt(curl_, CURLOPT_HEADERFUNCTION, HeaderCallback4Download);
::curl_easy_setopt(curl_, CURLOPT_HEADERDATA, &dld_ctx);
::curl_easy_setopt(curl_, CURLOPT_WRITEFUNCTION, WriteCallback4Download);
::curl_easy_setopt(curl_, CURLOPT_WRITEDATA, &dld_ctx);
//设置进度
::curl_easy_setopt(curl_, CURLOPT_NOPROGRESS, 0L);
::curl_easy_setopt(curl_, CURLOPT_PROGRESSFUNCTION, ProgressCallback4Download);
::curl_easy_setopt(curl_, CURLOPT_PROGRESSDATA, &dld_ctx);

::curl_easy_perform(curl_);

//暂时不考虑重定向

下面是完整源码:
CurlClient.h

#pragma once
#include <vector>
#include <string>
#include "curl.h"
#include "easy.h"


enum ESrcEncode{ EnUrlCode, EnUtf8Code };//默认EnUrlCode
#define SAFE_FREE(p) if(p != NULL){free(p);p=NULL;}
struct CurlChunk
{
	char* buf;
	size_t size;

	CurlChunk()
	{
		buf = NULL;
		size = 0;
	}

	~CurlChunk()
	{
		SAFE_FREE(buf);
	}
};

// 下载回调函数,返回0继续下载,否则停止下载
typedef int (*CurlDownloadSink)(const std::string& file_name,
								double dltotal,
								double dlnow,
								void* userp);

class CurlClient
{

public:
	CurlClient();
	~CurlClient();

public:
	static int GlobalInit();
	static void GlobalCleanup();
	static const char* GetErrMsg(CURLcode code);

	CURLcode DoHttpGet(CurlChunk& rsp,
					   const std::string& url,
					   const std::string& data,
					   long timeout = 10,
					   long with_header = 0);

	CURLcode DoHttpPost(CurlChunk& rsp,
						const std::string& url,
						const char* data,
						const int data_len,
						long timeout = 10,
                        long with_header = 0,
						std::vector<std::string> vHeader = std::vector<std::string>());

	CURLcode DownloadFile(const std::string& url,
						  const std::string& save_dir,
						  std::string& file_name,
						  CurlDownloadSink sink = NULL,
						  void* userp = NULL,
						  std::string user_agent = "",
						  ESrcEncode srcEncode = EnUrlCode,
						  bool bHead = false,
						  bool bResetLevel = true);

private:
	static size_t WriteCallback4Http(void* contents,
									 size_t size,
									 size_t nmemb,
									 void* userp);

	static size_t HeaderCallback4Download(char *ptr,
										  size_t size,
										  size_t nmemb,
										  void *userdata);

	static size_t WriteCallback4Download(char *ptr,
										 size_t size,
										 size_t nmemb,
										 void *userdata);

	static int ProgressCallback4Download(void *userdata,
										 double dltotal,
										 double dlnow,
										 double ultotal,
										 double ulnow);

private:
	CURL* curl_;
	int m_nRecurLevel;//重定次数
};

CurlClient.cpp

#include <fstream>
#include "CurlClient.h"
#include <Shlwapi.h>
#pragma comment(lib, "Shlwapi.lib")

#pragma warning(disable: 4996) // 'function': was declared deprecated

#define CURL_USER_AGENT "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36"


struct CurlDownloadContext
{
	CURL* curl;
	double total_time;
	CurlDownloadSink sink;
	void* userp;
	std::string save_dir;
	std::string file_name;
	UINT64 file_size;
	FILE* file;
	std::string redirect_url;
	ESrcEncode eSrcEncode;//下载文件名的编码方式
	CurlDownloadContext()
	{
		file_size = 0;
		curl = NULL;
		total_time = 0;
		sink = NULL;
		userp = NULL;
		file = NULL;
		eSrcEncode = EnUrlCode;
	}

	~CurlDownloadContext()
	{
		if (file != NULL)
		{
			fclose(file);
		}
	}
};

int CurlClient::GlobalInit()
{
	CURLcode ret = ::curl_global_init(CURL_GLOBAL_ALL);
	if (ret != CURLE_OK)
	{
		return -1;
	}
	return 0;
}

void CurlClient::GlobalCleanup()
{
	::curl_global_cleanup();
}

const char* CurlClient::GetErrMsg(CURLcode code)
{
	return ::curl_easy_strerror(code);
}

CurlClient::CurlClient()
{
	curl_ = ::curl_easy_init();
	m_nRecurLevel = 0;
}

CurlClient::~CurlClient()
{
	if (curl_ != NULL)
	{
		::curl_easy_cleanup(curl_);
	}
}

CURLcode CurlClient::DoHttpGet(CurlChunk& rsp,
							   const std::string& url,
							   const std::string& data,
							   long timeout,
							   long with_header)
{
	if (curl_ == NULL || url.empty())
	{
		return CURLE_BAD_FUNCTION_ARGUMENT;
	}

	std::string final_url(url);
	if (!data.empty())
	{
		final_url.append("?");
		final_url.append(data);
	}

	::curl_easy_reset(curl_);

	::curl_easy_setopt(curl_, CURLOPT_URL, final_url.c_str());
	::curl_easy_setopt(curl_, CURLOPT_HTTPGET, 1);
	::curl_easy_setopt(curl_, CURLOPT_HEADER, with_header);
	::curl_easy_setopt(curl_, CURLOPT_TIMEOUT, timeout);
	::curl_easy_setopt(curl_, CURLOPT_WRITEFUNCTION, WriteCallback4Http);
	::curl_easy_setopt(curl_, CURLOPT_WRITEDATA, (void*) &rsp);
	::curl_easy_setopt(curl_, CURLOPT_NOSIGNAL, 1);

	return ::curl_easy_perform(curl_);
}

CURLcode CurlClient::DoHttpPost(CurlChunk& rsp,
								const std::string& url,
								const char* data,
								const int data_len,
								long timeout,
								long with_header,
								std::vector<std::string> vHeader)
{
	if (curl_ == NULL || url.empty() || data == NULL || data_len == 0)
	{
		return CURLE_BAD_FUNCTION_ARGUMENT;
	}

	::curl_easy_reset(curl_);

	::curl_easy_setopt(curl_, CURLOPT_URL, url.c_str());
	::curl_easy_setopt(curl_, CURLOPT_POST, 1);
	::curl_easy_setopt(curl_, CURLOPT_HEADER, with_header);
	//构建HTTP报文头
	if (!vHeader.empty())
	{
		struct curl_slist* headers = NULL;
		for (int i = 0; i < vHeader.size();++i)
		{
			headers = curl_slist_append(headers, vHeader[i].c_str());
		}
		curl_easy_setopt(curl_, CURLOPT_HTTPHEADER, headers);
	}
	::curl_easy_setopt(curl_, CURLOPT_POSTFIELDS, data);
	::curl_easy_setopt(curl_, CURLOPT_POSTFIELDSIZE, data_len);
	::curl_easy_setopt(curl_, CURLOPT_TIMEOUT, timeout);
	::curl_easy_setopt(curl_, CURLOPT_WRITEFUNCTION, WriteCallback4Http);
	::curl_easy_setopt(curl_, CURLOPT_WRITEDATA, (void*) &rsp);
	::curl_easy_setopt(curl_, CURLOPT_SSL_VERIFYPEER, 0L);
	::curl_easy_setopt(curl_, CURLOPT_SSL_VERIFYHOST, 0L);
	::curl_easy_setopt(curl_, CURLOPT_NOSIGNAL, 1);


	return ::curl_easy_perform(curl_);
}

size_t CurlClient::WriteCallback4Http(void* contents,
									  size_t size,
									  size_t nmemb,
									  void* userp)
{
    const size_t real_size = size * nmemb;
    struct CurlChunk* chunk = (struct CurlChunk*) userp;

    chunk->buf = (char*) realloc(chunk->buf, chunk->size + real_size + 1);
    if (chunk->buf == NULL)
    {
        return 0;
    }

    memcpy(&(chunk->buf[chunk->size]), contents, real_size);
    chunk->size += real_size;
    chunk->buf[chunk->size] = '\0';

    return real_size;
}

bool ParseCurlLink(const std::string& url, std::string& file_name)
{
	size_t pos = url.find("://");
	size_t end_pos = std::string::npos;
	if (pos == std::string::npos)
		return false;

	std::string url_name = url.substr(pos + strlen("://"));
	//StringUtil::rtrim(StringUtil::trim(url_name), "/");

	pos = url_name.rfind('/');
	if (pos == std::string::npos)
		file_name.assign("index.html");
	else
	{
		end_pos = url_name.find_first_of("?", pos + 1);
		if (end_pos != std::string::npos)
			file_name = url_name.substr(pos + 1, end_pos - pos - 1);
		else
			file_name = url_name.substr(pos + 1);
	}


	return true;
}

CURLcode CurlClient::DownloadFile(const std::string& url,
								  const std::string& save_dir,
								  std::string& file_name,
								  CurlDownloadSink sink,
								  void* userp,
								  std::string user_agent,
								  ESrcEncode srcEncode,
								  bool bHead,
								  bool bResetLevel)
{
	if (bResetLevel)
	{
		m_nRecurLevel = 0;
	}
	++m_nRecurLevel;
	//递归深度默认为三次
	if (curl_ == NULL || url.empty() || save_dir.empty() || m_nRecurLevel > 3)
	{
		return CURLE_BAD_FUNCTION_ARGUMENT;
	}

	CurlDownloadContext dld_ctx;
	dld_ctx.curl = curl_;
	dld_ctx.sink = sink;
	dld_ctx.userp = userp;
	dld_ctx.eSrcEncode = srcEncode;
	dld_ctx.save_dir = save_dir;
	dld_ctx.file_name = file_name;

	if (save_dir[save_dir.length() - 1] != '\\')
	{
		dld_ctx.save_dir.append("\\");
	}

	if (dld_ctx.file_name.empty() && !ParseCurlLink(url, dld_ctx.file_name))
	{
		return CURLE_URL_MALFORMAT;
	}

	//防止curl重定向导致的名称不对
	if(file_name.empty() ||file_name == "")
		file_name = dld_ctx.file_name;

	::curl_easy_reset(curl_);

	::curl_easy_setopt(curl_, CURLOPT_URL, url.c_str());
	::curl_easy_setopt(curl_, CURLOPT_HTTPGET, 1L);
	::curl_easy_setopt(curl_, CURLOPT_CONNECTTIMEOUT, 300L);
	::curl_easy_setopt(curl_, CURLOPT_LOW_SPEED_TIME, 1800L);
	::curl_easy_setopt(curl_, CURLOPT_LOW_SPEED_LIMIT, 10L);
	::curl_easy_setopt(curl_, CURLOPT_USERAGENT, CURL_USER_AGENT);
	::curl_easy_setopt(curl_, CURLOPT_SSL_VERIFYPEER, 0L);
	::curl_easy_setopt(curl_, CURLOPT_SSL_VERIFYHOST, 0L);
	::curl_easy_setopt(curl_, CURLOPT_NOSIGNAL, 1L);
	if(bHead)
		::curl_easy_setopt(curl_,CURLOPT_NOBODY,1L);
	//构建HTTP报文头
	if(user_agent != "")
	{
		struct curl_slist* headers = NULL;
		headers = curl_slist_append(headers, user_agent.c_str());
		curl_easy_setopt(curl_, CURLOPT_HTTPHEADER, headers);
	}
	::curl_easy_setopt(curl_, CURLOPT_HEADERFUNCTION, HeaderCallback4Download);
	::curl_easy_setopt(curl_, CURLOPT_HEADERDATA, &dld_ctx);
	::curl_easy_setopt(curl_, CURLOPT_WRITEFUNCTION, WriteCallback4Download);
	::curl_easy_setopt(curl_, CURLOPT_WRITEDATA, &dld_ctx);

	if (!bHead && sink != NULL)
	{
		::curl_easy_setopt(curl_, CURLOPT_NOPROGRESS, 0L);
		::curl_easy_setopt(curl_, CURLOPT_PROGRESSFUNCTION, ProgressCallback4Download);
		::curl_easy_setopt(curl_, CURLOPT_PROGRESSDATA, &dld_ctx);
	}

	CURLcode ret = ::curl_easy_perform(curl_);
	if (ret == CURLE_OK)
	{
		if (!dld_ctx.redirect_url.empty() &&
			dld_ctx.redirect_url != url)
		{
			return DownloadFile(dld_ctx.redirect_url, save_dir, file_name, sink, userp,user_agent,srcEncode,bHead,false);
		}

		file_name = dld_ctx.file_name;
		if (!bHead && dld_ctx.file == NULL)
		{
			std::string file_path = dld_ctx.save_dir + dld_ctx.file_name;
			std::ofstream fout(file_path);
			fout.close();
		}
	}
	
	//通过返回码判断文件是否下载成功
	long retcode = 0;
	CURLcode code = curl_easy_getinfo(curl_, CURLINFO_RESPONSE_CODE, &retcode);
	if ((code == CURLE_OK) && retcode < 400)
	{
		return CURLE_OK;
	}
	return CURLE_BAD_FUNCTION_ARGUMENT;
}

size_t CurlClient::HeaderCallback4Download(char *ptr,
										   size_t size,
										   size_t nmemb,
										   void *userdata)
{
	CurlDownloadContext* dld_ctx = (CurlDownloadContext*)userdata;
	const char key_loc[] = "Location:";
	const char key_disp[] = "Content-Disposition:";
	const char key_fn[] = "filename=";
	const char key_length[] = "Content-Length:";

	if (_strnicmp(ptr, key_loc, strlen(key_loc)) == 0)
	{
		dld_ctx->redirect_url.assign(ptr + strlen(key_loc));
		//去掉\r\n
		if (dld_ctx->redirect_url.size() > 2)
		{
			dld_ctx->redirect_url.resize(dld_ctx->redirect_url.size() - 2);
		}
	}
	else if(_strnicmp(ptr, key_length, strlen(key_length)) == 0)
	{
		std::string file_length(ptr + strlen(key_length));
		dld_ctx->file_size = _atoi64(file_length.c_str());
	}
	else if (_strnicmp(ptr, key_disp, strlen(key_disp)) == 0)
	{
		char* fn = StrStrIA(ptr, key_fn);
		if (fn != NULL)
		{
			fn += strlen(key_fn);
			char* sep = strchr(fn, ';');
			dld_ctx->file_name.assign(fn, (sep == NULL ? strlen(fn) : sep - fn));
			//if(dld_ctx->eSrcEncode == EnUtf8Code)
				//StringUtil::Utf8ToAnsi(std::string(dld_ctx->file_name),dld_ctx->file_name);
			//else 
				//dld_ctx->file_name = StringUtil::UrlDecode(dld_ctx->file_name);

			//StringUtil::trim(StringUtil::trim(dld_ctx->file_name), "\"");
		}
	}

	return size * nmemb;
}

size_t CurlClient::WriteCallback4Download(char *ptr,
										  size_t size,
										  size_t nmemb,
										  void *userdata)
{
	CurlDownloadContext* dld_ctx = (CurlDownloadContext*)userdata;

	if (!dld_ctx->redirect_url.empty())
	{
		return size * nmemb;
	}
	
	if (dld_ctx->file == NULL)
	{
		std::string file_path = dld_ctx->save_dir + dld_ctx->file_name;
		dld_ctx->file = fopen(file_path.c_str(), "wb");
		if (dld_ctx->file == NULL)
		{
			return 0;
		}
	}

	return fwrite(ptr, size, nmemb, dld_ctx->file);
}

int CurlClient::ProgressCallback4Download(void *userdata,
										  double dltotal,
										  double dlnow,
										  double ultotal,
										  double ulnow)
{
	CurlDownloadContext* dld_ctx = (CurlDownloadContext*)userdata;

	if (dld_ctx->file_name.empty() || !dld_ctx->redirect_url.empty())
	{
		return 0;
	}

	double total_time = 0;
	::curl_easy_getinfo(dld_ctx->curl, CURLINFO_TOTAL_TIME, &total_time);

	if (dld_ctx->total_time == 0 || total_time - dld_ctx->total_time > 1)
	{
		dld_ctx->total_time = total_time;
		if (dld_ctx->sink(dld_ctx->file_name, dltotal, dlnow, dld_ctx->userp) != 0)
		{
			return 1;
		}
	}

	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值