C++ vs2017 - libcurl - http请求 代码大全(请求数据,上传下载文件,多线程上传下载文件)

Posted cpp_learners

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++ vs2017 - libcurl - http请求 代码大全(请求数据,上传下载文件,多线程上传下载文件)相关的知识,希望对你有一定的参考价值。

在网上搜寻各种libcurl的用法,将代码集合于此!



一、配置curl项目

  1. 下载curl
    下载链接:https://curl.se/download.html

    下载后解压!

  2. 编译curl库
    依次打开路径,找到vs工程并双击打开!


    右键 - 属性 - 配置属性 - 常规 - Windows SDK 版本 - 选择自己对应的哪个版本

    修改编译为DLL Debug x64

最后右键curl,重新生成即可!

生成成功后在项目文件夹中会多出一个build文件夹,其中我们需要的lib就在里面

  1. 打开vs创建一个项目
    将include文件夹和libcurld.lib 和 .dll 拷贝到自己新建的项目路径中

    拷贝后开始添加链接库

  2. 测试
    curl :get、pos请求,将请求到的数据写入get.html 和 post.html文件中。

#include <stdio.h>
#include "./include/curl/curl.h"

bool getUrl(const char *filename) 
	CURL *curl;			// CURL void
	CURLcode res;		// CURLcode 枚举
	FILE *fp;
	//if ((fp = fopen(filename, "w")) == NULL)  // 返回结果用文件存储
	//	return false;

	errno_t err = fopen_s(&fp, filename, "w");
	if (err != 0) 
		printf("open file error!\\n");
		return false;
	

	res = curl_global_init(CURL_GLOBAL_ALL);

	struct curl_slist *headers = NULL;
	headers = curl_slist_append(headers, "Accept: Agent-007");
	//headers = curl_slist_append(headers, "Accept:");
	curl = curl_easy_init();    // 初始化
	if (curl) 
		//curl_easy_setopt(curl, CURLOPT_PROXY, "10.99.60.201:8080");// 代理
		curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);// 改协议头
		curl_easy_setopt(curl, CURLOPT_URL, "www.baidu.com");
		curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp); //将返回的html主体数据输出到fp指向的文件
		curl_easy_setopt(curl, CURLOPT_HEADERDATA, fp); //将返回的http头输出到fp指向的文件
		res = curl_easy_perform(curl);   // 执行

		char *cal = curl_version();
		printf("curl_version = %s", cal);

		if (res != 0) 

			curl_slist_free_all(headers);
			curl_easy_cleanup(curl);
			curl_global_cleanup();
		
		fclose(fp);
		return true;
	

	fclose(fp);
	return false;



bool postUrl(const char *filename) 
	CURL *curl;
	CURLcode res;
	FILE *fp;
	//if ((fp = fopen(filename, "w")) == NULL)
	//	return false;

	errno_t err = fopen_s(&fp, filename, "w");
	if (err != 0) 
		printf("open file error!\\n");
		return false;
	

	curl = curl_easy_init();
	if (curl) 
		curl_easy_setopt(curl, CURLOPT_COOKIEFILE, "cookie.txt"); // 指定cookie文件
		curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "&logintype=uid&u=xieyan&psw=xxx86");    // 指定post内容
		curl_easy_setopt(curl, CURLOPT_URL, "www.baidu.com");   // 指定url
		curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
		res = curl_easy_perform(curl);
		curl_easy_cleanup(curl);
	
	fclose(fp);
	return true;





int main(void) 
	getUrl("get.html");
	postUrl("post.html");


	system("pause");
	return 0;


二、案例

这里我就不讲解知识点了,网上我看到有其他博客写的很详细的了!

1. 使用回调函数将请求到的数据写入文件中

// 使用回调函数将请求到的数据写入文件中

#include <iostream>
#include <string>
#include "include/curl/curl.h"

using namespace std;

size_t ncWriteFile(void *buffer, size_t size, size_t nmemb, void *lpVoid) 
	FILE *stream = (FILE *)lpVoid;

	if (stream == NULL || buffer == NULL) 
		return -1;
	
	size_t nWrite = fwrite(buffer, size, nmemb, stream);	// 写入文件

	return nWrite;


void SendGet() 
	FILE *fp;

	errno_t err = fopen_s(&fp, "1.txt", "w");
	if (err != 0) 
		cout << "文件打开失败!" << endl;
		return;
	

	CURL *curl;
	CURLcode res;

	struct curl_slist * headers = NULL;
	headers = curl_slist_append(headers, "Content-Type:application/json");
	//std::string url = "192.168.74.1";
	std::string url = "www.baidu.com";
	
	curl = curl_easy_init();	// 初始化
	if (curl) 
		curl_easy_setopt(curl, CURLOPT_URL, url.c_str());			// 请求地址
		curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);		// 请求头
		curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, ncWriteFile);	// 写入数据的回调函数
		curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)fp);		// 文件指针
		res = curl_easy_perform(curl);	// 执行

		if (res != 0) 
			curl_slist_free_all(headers);
			curl_easy_cleanup(curl);
		
	

	fclose(fp);



void SendPost() 
	CURL *curl;
	CURLcode res;

	struct curl_slist *headers = NULL;
	headers = curl_slist_append(headers, "Content-Type:application/json");
	//std::string url = "192.168.74.1";
	std::string url = "www.baidu.com";
	curl = curl_easy_init();		// 初始化
	if (curl) 
		curl_easy_setopt(curl, CURLOPT_URL, url.c_str());		// 请求地址
		curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);	// 请求头
		curl_easy_setopt(curl, CURLOPT_POSTFIELDS, NULL);		// 请求参数
		curl_easy_setopt(curl, CURLOPT_POST, 1);	// 设置非0表示本次操作位post请求
		res = curl_easy_perform(curl);		// 执行
		if (res != 0) 
			curl_slist_free_all(headers);
			curl_easy_cleanup(curl);
		
	



int main3(void) 
	SendGet();
	SendPost();

	return 0;

2. 上传文件到FTP

/* File FTP upload */


#include <iostream>
#include <string>
#include "include/curl/curl.h"

size_t read_data(void *buffer, size_t size, size_t nmemb, void *user_p) 
	return fread(buffer, size, nmemb, (FILE *)user_p);


BOOL filesUpload() 
	// 初始化libcurl
	CURLcode code;
	code = curl_global_init(CURL_GLOBAL_WIN32);
	if (code != CURLE_OK) 
		std::cout << "init libcurl failed." << std::endl;
		return FALSE;
	

	FILE *fp = NULL;
	errno_t err = fopen_s(&fp, "text.html", "rb");
	if (err != 0) 
		std::cout << "open file text.html fail!" << std::endl;
		return FALSE;
	

	// 获取文件大小
	int fileSize = ftell(fp);
	rewind(fp);	// 文件指针定位到开头

	// 获取easy handle
	CURL *easy_handle = NULL;
	easy_handle = curl_easy_init();
	if (easy_handle == NULL) 
		std::cout << "get a seay handle failed." << std::endl;
		fclose(fp);
		curl_global_cleanup();
		return FALSE;
	

	// 设置eash handle 属性
	curl_easy_setopt(easy_handle, CURLOPT_URL, "ftp://***");
	curl_easy_setopt(easy_handle, CURLOPT_UPLOAD, 1L);		// 告诉libcurl,执行的是上传操作
	curl_easy_setopt(easy_handle, CURLOPT_READFUNCTION, &read_data);	// 设置回调函数
	curl_easy_setopt(easy_handle, CURLOPT_READDATA, &fp);	// 设置回调函数最后一个参数
	curl_easy_setopt(easy_handle, CURLOPT_INFILESIZE_LARGE, fileSize);	// 告诉libcurl要上传文件的大小
	
	// 执行上传操作
	code = curl_easy_perform(easy_handle);
	if (code != CURLE_OK) 
		std::cout << "upload file failed." << std::endl;
		return FALSE;
	

	// 释放资源
	fclose(fp);
	curl_easy_cleanup(easy_handle);
	curl_global_cleanup();

	return TRUE;



int main4(void) 

	filesUpload();

	return 0;

3. curl_formadd - 表单文件上传和上传数据

/* curl_formadd表单文件上传和上传数据 */

#include <iostream>
#include "include/curl/curl.h"
#include <string>

using namespace std;

//回调函数  得到响应内容
int write_data(void* buffer, int size, int nmemb, void* userp) 
	std::string* str = dynamic_cast<std::string*>((std::string*)userp);
	str->append((char*)buffer, size * nmemb);
	return nmemb;

int upload(string url, string& body, string* response);

int main(int argc, char** argv) 

	std::string body;
	std::string response;

	int status_code = upload("192.168.74.1", body, &response);
	if (status_code != CURLcode::CURLE_OK) 
		return -1;
	
	cout << body << endl;
	cout << response << endl;

	return 0;


int upload(string url, string& body, string* response) 
	CURL* curl;
	CURLcode ret;
	curl = curl_easy_init();
	struct curl_httppost* post = NULL;
	struct curl_httppost* last = NULL;
	

	if (curl) 
		curl_easy_setopt(curl, CURLOPT_URL, (char*)url.c_str());           //指定url

		// 表单上传
		curl_formadd(&post, &last, CURLFORM_PTRNAME, "name", CURLFORM_PTRCONTENTS, "ggggggg", CURLFORM_END);//form-data key(path) 和 value(device_cover)
		curl_formadd(&post, &last, CURLFORM_PTRNAME, "sex", CURLFORM_PTRCONTENTS, "1", CURLFORM_END);//form-data key(path) 和 value(device_cover)
		
		// 文件上传																	// 指定上传后的名字为1.pdf
		curl_formadd(&post, &last, CURLFORM_PTRNAME, "file", CURLFORM_FILE, "1.html", CURLFORM_FILENAME, "1.pdf", CURLFORM_END);

		curl_easy_setopt(curl, CURLOPT_HTTPPOST, post);                     // 构造post参数  通过此操作将文件操作绑定上传 
		curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);          // 绑定相应
		curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void*)response);        // 绑定响应内容的地址

		ret = curl_easy_perform(curl);                          //执行请求
		if (ret == 0) 
			curl_easy_cleanup(curl);
			return 0;
		 else 
			return ret;
		
	 else 
		return -1;
	

4. 小插曲 - 验证是否上传成功

文件按和数据是上传了,但是我该怎么知道有没有上传成功呢?

因为我们有没有可以验证的服务器!

没关系,可以下载一个小工具进行验证,名字叫:NetAssist

下载后打开是这样的:

然后:

然后你再次运行程序:

可以看到设置的数据和文件数据都已经上传到TCP服务器了,这就证明上传成功了!

5. C++用libcurl通过HTTP以表单的方式Post数据到服务器


/* C++用libcurl通过HTTP以表单的方式Post数据到服务器 */

#if 0
// post字符串,将字符串上传
#include <stdio.h>
#include "include/curl/curl.h"

int main(void) 

	CURL *curl = NULL;
	CURLcode res;

	curl = curl_easy_init();	// 初始化
	if (curl == NULL) 
		return CURLE_FAILED_INIT;
	

	struct curl_slist *headerlist = NULL;

	// 设置表头
	headerlist = curl_slist_append(headerlist, "Content-Type:application/x-www-form-urlencoded");
	curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist);

	// 设置URL
	curl_easy_setopt(curl, CURLOPT_URL, "192.168.74.1");

	// 设置参数
	curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "name=guangzhou&project=tianhe");

	// 设置为Post
	curl_easy_setopt(curl, CURLOPT_POST, 1);

	// 执行
	res = curl_easy_perform(curl);
	if (res != CURLE_OK) 
		// 获取详细信息
		const char *szErr = curl_easy_strerror(res);
		fprintf(stderr, "curl_easy_perform() failed : %s\\n", szErr);
	

	// 清空
	curl_easy_cleanup(curl);

	// 释放表头
	curl_slist_free_all(headerlist);

	return 0;


#endif


#if 0
/* 表单上传数据和文件 */
#include <stdio.h>
#include <string>
#include "include/curl/curl.h"

size_t onWriteData(void *buffer, size_t size, size_t nmemb, void *lpVoid);

int main(void) 

	CURL *curl = NULL;
	CURLcode res;

	curl = curl_easy_init();
	if (curl == NULL) 
		return CURLE_FAILED_INIT;
	

	struct curl_slist *headerlist = NULL;
	struct curl_httppost *formpost = NULL;
	struct curl_httppost *lastptr = NULLwin10上使用VS2017编译libcurl

win10上使用VS2017编译libcurl

Windows下用vs2017编译和配置libcurl库(手把手教,适合新人)

C++进阶详解C++开源网络传输库libcurl的编译过程

GuzzleHttp\Exception\RequestException cURL 错误 3:(参见 https://curl.haxx.se/libcurl/c/libcurl-errors.ht

如何正确安装 libcurl 以在 Visual Studio 2017 中使用?