在网上搜寻各种libcurl的用法,将代码集合于此!
生成成功后在项目文件夹中会多出一个build文件夹,其中我们需要的lib就在里面
测试
curl :get、pos请求,将请求到的数据写入get.html 和 post.html文件中。
#include
#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;
}
这里我就不讲解知识点了,网上我看到有其他博客写的很详细的了!
// 使用回调函数将请求到的数据写入文件中
#include
#include
#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;
}
/* File FTP upload */
#include
#include
#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;
}
/* curl_formadd表单文件上传和上传数据 */
#include
#include "include/curl/curl.h"
#include
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;
}
}
文件按和数据是上传了,但是我该怎么知道有没有上传成功呢?
因为我们有没有可以验证的服务器!
没关系,可以下载一个小工具进行验证,名字叫:NetAssist
然后你再次运行程序:
可以看到设置的数据和文件数据都已经上传到TCP服务器了,这就证明上传成功了!
/* C++用libcurl通过HTTP以表单的方式Post数据到服务器 */
#if 0
// post字符串,将字符串上传
#include
#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
#include
#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 = NULL;
std::string strResponse; // 回复
// 设置要上传的数据
curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "ParamName1", CURLFORM_COPYCONTENTS, "ParamName1Content", CURLFORM_END);
curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "ParamName2", CURLFORM_COPYCONTENTS, "ParamName2Content", CURLFORM_END);
curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "ParamName3", CURLFORM_COPYCONTENTS, "ParamName3Content", CURLFORM_END);
// 设置要上传的文件
curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "registerImage", CURLFORM_FILE, "Image.png", CURLFORM_CONTENTTYPE, "application/x-png", CURLFORM_END);
curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "html", CURLFORM_FILE, "1.html", CURLFORM_END);
curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "html", CURLFORM_FILE, "text.html", CURLFORM_END);
curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "txt", CURLFORM_FILE, "text.txt", CURLFORM_END);
/* curl_formadd(&post, &last, CURLFORM_COPYNAME, "file", CURLFORM_FILE, filepath, CURLFORM_CONTENTTYPE, "application/x-jpg", CURLFORM_END);
//application/x-jpg是jpg文件的类型,具体要根据自己上传的文件类型进行设置,参考http://tools.jb51.net/table/http_content_type */
// 设置表头
headerlist = curl_slist_append(headerlist, "Content-Type:application/urlencoded");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist);
// 设置URL
curl_easy_setopt(curl, CURLOPT_URL, "http://192.168.74.1");
// 现在指定POST数据
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "name=guangzhou&project=panyu");
// 设置位post
curl_easy_setopt(curl, CURLOPT_POST, 1);
curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost); //构造post参数
curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, onWriteData);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&strResponse);
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
//curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3);
//curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3);
// 执行
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_formfree(formpost);
// 释放表头
curl_slist_free_all(headerlist);
return 0;
}
size_t onWriteData(void *buffer, size_t size, size_t nmemb, void *lpVoid) {
std::string *str = dynamic_cast<std::string *>((std::string *)lpVoid);
if (str == NULL || buffer == NULL) {
return -1;
}
char *pData = (char *)buffer;
str->append(pData, size * nmemb);
return nmemb;
}
#endif
/* 使用回调函数文件上传 */
#include
#include "include/curl/curl.h"
#include
#include
size_t readData(void *buffer, size_t size, size_t nmemb, void *user_p) {
return fread(buffer, size, nmemb, (FILE *)user_p);
}
int main7(void) {
CURL *curl;
CURLcode res;
struct stat file_info;
curl_off_t speed_upload, total_time;
FILE *fd;
errno_t err = fopen_s(&fd, "text.txt", "rb");
if (err != 0) {
printf("open file 1.html fail!\n");
return -1;
}
if (fstat(_fileno(fd), &file_info) != 0) {
return -1;
}
curl = curl_easy_init();
if (curl) {
// 上传到这个位置
curl_easy_setopt(curl, CURLOPT_URL, "192.168.74.1");
// 告诉他上传到URL
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
// 告诉他从Windows上读取文件上传
curl_easy_setopt(curl, CURLOPT_READDATA, fd);
curl_easy_setopt(curl, CURLOPT_READFUNCTION, readData);
// 并给出上传的大小
curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)file_info.st_size);
// 启用详细信息以更容易跟踪
//curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
res = curl_easy_perform(curl);
if (res != CURLE_OK) {
// 打印错误信息
fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
} else {
// 提取信息
curl_easy_getinfo(curl, CURLINFO_SPEED_UPLOAD_T, &speed_upload);
curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME_T, &total_time);
fprintf(stderr, "Speed: %" CURL_FORMAT_CURL_OFF_T " bytes/sec during %"
CURL_FORMAT_CURL_OFF_T ".%06ld seconds\n",
speed_upload,
(total_time / 1000000), (long)(total_time % 1000000));
}
// 释放
curl_easy_cleanup(curl);
}
fclose(fd);
return 0;
}
/* 通过回调函数上传数据 */
#include
#include
#include "include/curl/curl.h"
#define USE_CHUNKED 1
/* silly test data to POST */
static const char data[] = "Lorem ipsum dolor sit amet, consectetur adipiscing "
"elit. Sed vel urna neque. Ut quis leo metus. Quisque eleifend, ex at "
"laoreet rhoncus, odio ipsum semper metus, at tempus ante urna in mauris. "
"Suspendisse ornare tempor venenatis. Ut dui neque, pellentesque a varius "
"eget, mattis vitae ligula. Fusce ut pharetra est. Ut ullamcorper mi ac "
"sollicitudin semper. Praesent sit amet tellus varius, posuere nulla non, "
"rhoncus ipsum.";
struct WriteThis {
const char *readptr;
size_t sizeleft;
};
static size_t read_callback(char *dest, size_t size, size_t nmemb, void *userp) {
struct WriteThis *wt = (struct WriteThis *)userp;
size_t buffer_size = size * nmemb;
if (wt->sizeleft) {
/* copy as much as possible from the source to the destination */
size_t copy_this_much = wt->sizeleft;
if (copy_this_much > buffer_size)
copy_this_much = buffer_size;
memcpy(dest, wt->readptr, copy_this_much);
wt->readptr += copy_this_much;
wt->sizeleft -= copy_this_much;
return copy_this_much; /* we copied this many bytes */
}
return 0; /* no more data left to deliver */
}
int main8(void) {
CURL *curl;
CURLcode res;
struct WriteThis wt;
wt.readptr = data;
wt.sizeleft = strlen(data);
/* In windows, this will init the winsock stuff */
res = curl_global_init(CURL_GLOBAL_DEFAULT);
/* Check for errors */
if (res != CURLE_OK) {
fprintf(stderr, "curl_global_init() failed: %s\n",
curl_easy_strerror(res));
return 1;
}
/* get a curl handle */
curl = curl_easy_init();
if (curl) {
/* First set the URL that is about to receive our POST. */
curl_easy_setopt(curl, CURLOPT_URL, "192.168.74.1");
/* Now specify we want to POST data */
curl_easy_setopt(curl, CURLOPT_POST, 1L);
/* we want to use our own read function */
curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_callback);
/* pointer to pass to our read function */
curl_easy_setopt(curl, CURLOPT_READDATA, &wt);
/* get verbose debug output please */
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
/*
If you use POST to a HTTP 1.1 server, you can send data without knowing
the size before starting the POST if you use chunked encoding. You
enable this by adding a header like "Transfer-Encoding: chunked" with
CURLOPT_HTTPHEADER. With HTTP 1.0 or without chunked transfer, you must
specify the size in the request.
*/
#ifdef USE_CHUNKED
{
struct curl_slist *chunk = NULL;
chunk = curl_slist_append(chunk, "Transfer-Encoding: chunked");
res = curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk);
/* use curl_slist_free_all() after the *perform() call to free this
list again */
}
#else
/* Set the expected POST size. If you want to POST large amounts of data,
consider CURLOPT_POSTFIELDSIZE_LARGE */
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long)wt.sizeleft);
#endif
#ifdef DISABLE_EXPECT
/*
Using POST with HTTP 1.1 implies the use of a "Expect: 100-continue"
header. You can disable this header with CURLOPT_HTTPHEADER as usual.
NOTE: if you want chunked transfer too, you need to combine these two
since you can only set one list of headers with CURLOPT_HTTPHEADER. */
/* A less good option would be to enforce HTTP 1.0, but that might also
have other implications. */
{
struct curl_slist *chunk = NULL;
chunk = curl_slist_append(chunk, "Expect:");
res = curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk);
/* use curl_slist_free_all() after the *perform() call to free this
list again */
}
#endif
/* Perform the request, res will get the return code */
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);
}
curl_global_cleanup();
return 0;
}
/* curl_formadd - 表单上传多个文件 */
#include
#include
#include
#include "include/curl/curl.h"
#define PERM 0
int main9(void) {
CURL *curl;
CURLcode rcode;
const char *url = "192.168.74.1";
const char *head_t = "66666666";
char heads[1024];
struct curl_httppost *formpost = NULL;
struct curl_httppost *lastptr = NULL;
struct curl_slist *headers = NULL; /* init to NULL is important */
sprintf_s(heads, "head-sky:%s", head_t);
headers = curl_slist_append(headers, heads);
rcode = curl_global_init(CURL_GLOBAL_ALL);
if (CURLE_OK != rcode)
return 0;
curl = curl_easy_init();
if (NULL == curl)
curl_global_cleanup();
#if PERM == 1
/*设置发送单个文件*/
curl_formadd(&formpost,
&lastptr,
CURLFORM_COPYNAME, "sendfile",
CURLFORM_FILE, name,
CURLFORM_END);
#else
/*设置发送多个文件*/ // 方式一
struct curl_forms array[3];
array[0].option = CURLFORM_FILE;
array[0].value = "1.html";
array[1].option = CURLFORM_FILE;
array[1].value = "text.jpg";
array[2].option = CURLFORM_END;
curl_formadd(&formpost,
&lastptr,
CURLFORM_COPYNAME, "sendfile",
CURLFORM_ARRAY, array,
CURLFORM_END);
#endif
// 或者下面这种方式上传多个文件 // 方式二
curl_formadd(&formpost,
&lastptr,
CURLFORM_COPYNAME, "filename",
CURLFORM_COPYCONTENTS, "1.html",
CURLFORM_END);
curl_formadd(&formpost,
&lastptr,
CURLFORM_COPYNAME, "filename",
CURLFORM_COPYCONTENTS, "text.jpg",
CURLFORM_END);
curl_formadd(&formpost,
&lastptr,
CURLFORM_COPYNAME, "submit",
CURLFORM_COPYCONTENTS, "send",
CURLFORM_END);
/
//设置发送http头部
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
//设置url
curl_easy_setopt(curl, CURLOPT_URL, url);
//设置http以post方式请求
curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
//设置超时时间
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10L);
//发送数据
rcode = curl_easy_perform(curl);
if (rcode != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(rcode));
}
curl_formfree(formpost);
curl_easy_cleanup(curl);
curl_slist_free_all(headers);
curl_global_cleanup();
return 0;
}
/* curl_mime_data - 表单上传多个文件 */
#include
#include
#include "include/curl/curl.h"
int main10(void) {
CURL *curl;
CURLcode res;
curl_mime *form = NULL;
curl_mimepart *field = NULL;
struct curl_slist *headerlist = NULL;
static const char buf[] = "Expect:";
curl_global_init(CURL_GLOBAL_ALL);
curl = curl_easy_init();
if (curl == NULL) {
printf("curl_easy_init() init fail!\n");
curl_global_cleanup();
}
// 创建表单
form = curl_mime_init(curl);
// 填写文件上传字段
field = curl_mime_addpart(form);
curl_mime_name(field, "sendfile");
curl_mime_filedata(field, "1.html");
// 填写文件名字段
field = curl_mime_addpart(form);
curl_mime_name(field, "filename");
curl_mime_data(field, "1.html", CURL_ZERO_TERMINATED);
// 填写文件上传字段
field = curl_mime_addpart(form);
curl_mime_name(field, "sendfile");
curl_mime_filedata(field, "text.html");
// 填写文件名字段
field = curl_mime_addpart(form);
curl_mime_name(field, "filename");
curl_mime_data(field, "text.html", CURL_ZERO_TERMINATED);
// 填写提交字段
field = curl_mime_addpart(form);
curl_mime_name(field, "submit");
curl_mime_data(field, "send", CURL_ZERO_TERMINATED);
// 请求头
headerlist = curl_slist_append(headerlist, buf);
// URL
curl_easy_setopt(curl, CURLOPT_URL, "192.168.74.1");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist);
curl_easy_setopt(curl, CURLOPT_MIMEPOST, form);
// 执行
res = curl_easy_perform(curl);
if (res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s \n", curl_easy_strerror(res));
}
curl_easy_cleanup(curl);
curl_mime_free(form);
curl_slist_free_all(headerlist);
return 0;
}
/* 使用多线程上传多个文件 */
#include
#include "include/curl/curl.h"
#include
#include
#include
#include
#define UPLOAD_THREAD_COUNT 3
typedef struct U_FN {
char *urlArr;
char *filePathArr;
}UFN;
size_t readData2(void *buffer, size_t size, size_t nmemb, void *user_p) {
return fread(buffer, size, nmemb, (FILE *)user_p);
}
unsigned int WINAPI uploadFile(void *_ufn) {
UFN *ufn = (UFN *)_ufn;
CURL *curl;
CURLcode res;
struct stat file_info;
curl_off_t speed_upload, total_time;
FILE *fd;
//Sleep(100);
errno_t err = fopen_s(&fd, ufn->filePathArr, "rb");
if (err != 0) {
printf("open file %s fail!\n", ufn->filePathArr);
return -1;
}
if (fstat(_fileno(fd), &file_info) != 0) {
return -1;
}
curl = curl_easy_init();
if (curl) {
// 上传到这个位置
curl_easy_setopt(curl, CURLOPT_URL, ufn->urlArr);
// 告诉他上传到URL
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
// 告诉他从Windows上读取文件上传
curl_easy_setopt(curl, CURLOPT_READDATA, fd);
curl_easy_setopt(curl, CURLOPT_READFUNCTION, readData2);
// 并给出上传的大小
curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)file_info.st_size);
// 启用详细信息以更容易跟踪
//curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
res = curl_easy_perform(curl);
if (res != CURLE_OK) {
// 打印错误信息
fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
} else {
// 提取信息
curl_easy_getinfo(curl, CURLINFO_SPEED_UPLOAD_T, &speed_upload);
curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME_T, &total_time);
fprintf(stderr, "Speed: %" CURL_FORMAT_CURL_OFF_T " bytes/sec during %"
CURL_FORMAT_CURL_OFF_T ".%06ld seconds\n",
speed_upload,
(total_time / 1000000), (long)(total_time % 1000000));
}
// 释放
curl_easy_cleanup(curl);
}
fclose(fd);
return 0;
}
int main13(void) {
UFN ufn[UPLOAD_THREAD_COUNT];
ufn[0].filePathArr = (char *)"1.html";
ufn[0].urlArr = (char *)"192.168.74.1";
ufn[1].filePathArr = (char *)"text.jpg";
ufn[1].urlArr = (char *)"192.168.74.1";
ufn[2].filePathArr = (char *)"text.txt";
ufn[2].urlArr = (char *)"192.168.74.1";
HANDLE tHandles[UPLOAD_THREAD_COUNT];
for (int i = 0; i < UPLOAD_THREAD_COUNT; i++) {
// 至少需要加上20毫秒的延时,否则会连接失败!
Sleep(20);
tHandles[i] = (HANDLE)_beginthreadex(NULL, 0, uploadFile, (void *)&ufn[i], 0, NULL);
}
// 阻塞多个线程句柄,直到子线程运行完毕,主线程才会往下走
WaitForMultipleObjects(UPLOAD_THREAD_COUNT, tHandles, TRUE, INFINITE);
printf("%d个文件已经上传完成!\n", UPLOAD_THREAD_COUNT);
return 0;
}
可以通过CURLOPT_PROGRESSFUNCTION设置下载进度显示
/* 请求下载文件 */
#include
#include
#include
#include "./include/curl/curl.h"
#include "./include/curl/easy.h"
using namespace std;
// 这个函数是为了符合CURLOPT_WRITEFUNCTION而构造的
// 完成数据保存功能
size_t write_data(void *ptr, size_t size, size_t nmemb, void *stream) {
// 从ptr中读取数据写入文件流中
int written = fwrite(ptr, size, nmemb, (FILE *)stream);
return written;
}
// 这个函数是为了符合CURLOPT_PROGRESSFUNCTION而构造的
// 完成数据保存功能
int my_progress_func(char *progress_data, double dltotal, double dlnow, double ultotal, double ulnow) {
printf("%s 已下载:%.2f MB\n", progress_data, dlnow / (1024 * 1024));
Sleep(100);
return 0;
}
int main2(void) {
CURL *curl;
CURLcode res;
const char *progress_data = "* ";
// 定义FILE类型指针
FILE *fp = NULL;
res = curl_global_init(CURL_GLOBAL_ALL);
if (res != CURLE_OK) {
printf("curl_global_init(CURL_GLOBAL_ALL) is fail!\n");
exit(-1);
}
curl = curl_easy_init();
if (curl) {
errno_t err = fopen_s(&fp, "text.txt", "wb");
if (err != 0) {
printf("open file fail!\n");
exit(-1);
}
//curl_easy_setopt(curl, CURLOPT_URL, "192.168.74.1"); // 设置url链接
curl_easy_setopt(curl, CURLOPT_URL, "http://www.newbiquge.com/modules/article/txtarticle.php?id=4486"); // 设置url链接
// CURLOPT_WRITEFUNCTION 将后续的动作交给write_data函数处理
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
// 显示下载进度
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, FALSE);
curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, my_progress_func);
curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, progress_data);
// 不接收响应头数据0代表不接收 1代表接收
curl_easy_setopt(curl, CURLOPT_HEADER, 0);
res = curl_easy_perform(curl); // 执行
if (res != CURLE_OK) {
printf("curl_easy_perform(curl) is fail!\n");
curl_easy_cleanup(curl); // 释放
exit(-1);
}
curl_easy_cleanup(curl); // 释放
}
curl_global_cleanup();
fclose(fp);
return 0;
}
下载你可以使用一些网络监测工具查看是否有下载操作,例如我这里使用360加速球看的。
/* 同时下载多个文件 - 无法实现保存到本地,只能实现下载效果 */
#include
#include
#include
#include "include/curl/curl.h"
// 这些是下载的url
static const char *urls[] = {
"http://www.newbiquge.com/modules/article/txtarticle.php?id=4486",
"http://bpic.588ku.com/element_origin_min_pic/16/10/29/2ac8e99273bc079e40a8dc079ca11b1f.jpg"
};
#define MAX_PARALLEL 2
#define NUM_URLS sizeof(urls) / sizeof(char *)
static size_t write_cb(char *data, size_t n, size_t l, void *userp) {
// 忽略...
(void)data;
(void)userp;
return n * l;
}
static void add_transfer(CURLM *cm, int i) {
CURL *eh = curl_easy_init();
curl_easy_setopt(eh, CURLOPT_WRITEFUNCTION, write_cb);
curl_easy_setopt(eh, CURLOPT_URL, urls[i]);
// 在这把调用的网址存下,后面curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE, &url);查询出来
curl_easy_setopt(eh, CURLOPT_PRIVATE, urls[i]);
curl_multi_add_handle(cm, eh);
}
int main11(void) {
CURLM *cm;
CURLMsg *msg;
unsigned int transfers = 0;
int msgs_left = -1;
int still_alive = 1;
curl_global_init(CURL_GLOBAL_ALL);
cm = curl_multi_init();
// 限制同时连接的数量卷曲应该允许:
curl_multi_setopt(cm, CURLMOPT_MAXCONNECTS, (long)MAX_PARALLEL);
for (transfers = 0; transfers < MAX_PARALLEL; transfers++) {
add_transfer(cm, transfers);
}
do {
// 执行
curl_multi_perform(cm, &still_alive);
while ((msg = curl_multi_info_read(cm, &msgs_left))) {
if (msg->msg == CURLMSG_DONE) {
char *url;
CURL *e = msg->easy_handle;
curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE, &url);
fprintf(stderr, "R:%d - %s <%s>\n", msg->data.result, curl_easy_strerror(msg->data.result), url);
curl_multi_remove_handle(cm, e);
curl_easy_cleanup(e);
} else {
fprintf(stderr, "E:CURLMsg (%d) \n", msg->msg);
}
// 如果还有链接,继续添加,继续下载
if (transfers < NUM_URLS) {
add_transfer(cm, transfers++);
}
}
if (still_alive) {
curl_multi_wait(cm, NULL, 0, 1000, NULL);
}
} while (still_alive || (transfers < NUM_URLS));
curl_multi_cleanup(cm);
curl_global_cleanup();
return EXIT_SUCCESS;
}
/* 使用多线程请求下载多个文件 */
#include
#include
#include
#include
#include "./include/curl/curl.h"
#include "./include/curl/easy.h"
using namespace std;
#define THREAD_COUNT 2
typedef struct URL_FN {
char *urlArr;
char *filePathArr;
}UF;
// 这个函数是为了符合CURLOPT_WRITEFUNCTION而构造的
// 完成数据保存功能
size_t write_data2(void *ptr, size_t size, size_t nmemb, void *stream) {
// 从ptr中读取数据写入文件流中
int written = fwrite(ptr, size, nmemb, (FILE *)stream);
return written;
}
// 这个函数是为了符合CURLOPT_PROGRESSFUNCTION而构造的
// 完成数据保存功能
int my_progress_func2(char *progress_data, double dltotal, double dlnow, double ultotal, double ulnow) {
printf("%s 已下载:%.2f MB\n", progress_data, dlnow / (1024 * 1024));
return 0;
}
unsigned int WINAPI downloadFile(void *_uf) {
UF *uf = (UF *)_uf;
CURL *curl;
CURLcode res;
const char *progress_data = "* ";
// 定义FILE类型指针
FILE *fp = NULL;
res = curl_global_init(CURL_GLOBAL_ALL);
if (res != CURLE_OK) {
printf("curl_global_init(CURL_GLOBAL_ALL) is fail!\n");
return 0;
}
curl = curl_easy_init();
if (curl) {
errno_t err = fopen_s(&fp, uf->filePathArr, "wb");
if (err != 0) {
printf("open file %s fail!\n", uf->filePathArr);
return 0;
}
//curl_easy_setopt(curl, CURLOPT_URL, "192.168.74.1"); // 设置url链接
curl_easy_setopt(curl, CURLOPT_URL, uf->urlArr); // 设置url链接
// CURLOPT_WRITEFUNCTION 将后续的动作交给write_data函数处理
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data2);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
// 显示下载进度
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, FALSE);
curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, my_progress_func2);
curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, progress_data);
//不接收响应头数据0代表不接收 1代表接收
curl_easy_setopt(curl, CURLOPT_HEADER, 0);
curl_easy_perform(curl); // 执行
curl_easy_cleanup(curl); // 释放
}
curl_global_cleanup();
fclose(fp);
return 0;
}
int main12(void) {
UF uf[THREAD_COUNT];
// 设置下载的url和下载后保存的路径和文件名
uf[0].urlArr = (char *)"http://www.newbiquge.com/modules/article/txtarticle.php?id=4486";
uf[0].filePathArr = (char *)"C:\\Users\\gzsa\\Desktop\\abc.txt";
uf[1].urlArr = (char *)"http://bpic.588ku.com/element_origin_min_pic/16/10/29/2ac8e99273bc079e40a8dc079ca11b1f.jpg";
uf[1].filePathArr = (char *)"C:\\Users\\gzsa\\Desktop\\abc.jpg";
HANDLE tHandles[THREAD_COUNT];
for (int i = 0; i < THREAD_COUNT; i++) {
tHandles[i] = (HANDLE)_beginthreadex(NULL, 0, downloadFile, (void *)&uf[i], 0, NULL);
}
//for (int j = 0; j < 10000; j++) {
// printf("%d\n", j);
//}
// 阻塞多个线程句柄,直到子线程运行完毕,主线程才会往下走
WaitForMultipleObjects(THREAD_COUNT, tHandles, TRUE, INFINITE);
printf("%d个文件已经下载完成!\n", THREAD_COUNT);
return 0;
}
官方案例:https://curl.se/libcurl/c/example.html
这些案例都是在网上扒的和官网的案例,还有一些是自己写的,我只是将一些我觉得比较实用的例子记录下来!