在网上搜寻各种libcurl的用法,将代码集合于此!
一、配置curl项目
-
下载curl 下载链接:https://curl.se/download.html 下载后解压! -
编译curl库 依次打开路径,找到vs工程并双击打开! 右键 - 属性 - 配置属性 - 常规 - Windows SDK 版本 - 选择自己对应的哪个版本 修改编译为DLL Debug x64
最后右键curl,重新生成即可!
生成成功后在项目文件夹中会多出一个build文件夹,其中我们需要的lib就在里面
-
打开vs创建一个项目 将include文件夹和libcurld.lib 和 .dll 拷贝到自己新建的项目路径中 拷贝后开始添加链接库 -
测试 curl :get、pos请求,将请求到的数据写入get.html 和 post.html文件中。
#include <stdio.h>
#include "./include/curl/curl.h"
bool getUrl(const char *filename) {
CURL *curl;
CURLcode res;
FILE *fp;
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");
curl = curl_easy_init();
if (curl) {
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_URL, "www.baidu.com");
curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
curl_easy_setopt(curl, CURLOPT_HEADERDATA, 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;
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");
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "&logintype=uid&u=xieyan&psw=xxx86");
curl_easy_setopt(curl, CURLOPT_URL, "www.baidu.com");
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 = "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 = "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);
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
#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() {
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);
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;
}
curl_easy_setopt(easy_handle, CURLOPT_URL, "ftp://***");
curl_easy_setopt(easy_handle, CURLOPT_UPLOAD, 1L);
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);
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 - 表单文件上传和上传数据
#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());
curl_formadd(&post, &last, CURLFORM_PTRNAME, "name", CURLFORM_PTRCONTENTS, "ggggggg", CURLFORM_END);
curl_formadd(&post, &last, CURLFORM_PTRNAME, "sex", CURLFORM_PTRCONTENTS, "1", CURLFORM_END);
curl_formadd(&post, &last, CURLFORM_PTRNAME, "file", CURLFORM_FILE, "1.html", CURLFORM_FILENAME, "1.pdf", CURLFORM_END);
curl_easy_setopt(curl, CURLOPT_HTTPPOST, 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数据到服务器
#if 0
#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);
curl_easy_setopt(curl, CURLOPT_URL, "192.168.74.1");
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "name=guangzhou&project=tianhe");
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 = 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);
headerlist = curl_slist_append(headerlist, "Content-Type:application/urlencoded");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist);
curl_easy_setopt(curl, CURLOPT_URL, "http://192.168.74.1");
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "name=guangzhou&project=panyu");
curl_easy_setopt(curl, CURLOPT_POST, 1);
curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
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);
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
6. 使用回调函数文件上传
#include <stdio.h>
#include "include/curl/curl.h"
#include <fcntl.h>
#include <sys/stat.h>
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");
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
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);
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;
}
7. 通过回调函数上传数据
#include <stdio.h>
#include <string.h>
#include "include/curl/curl.h"
#define USE_CHUNKED 1
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) {
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;
}
return 0;
}
int main8(void) {
CURL *curl;
CURLcode res;
struct WriteThis wt;
wt.readptr = data;
wt.sizeleft = strlen(data);
res = curl_global_init(CURL_GLOBAL_DEFAULT);
if (res != CURLE_OK) {
fprintf(stderr, "curl_global_init() failed: %s\n",
curl_easy_strerror(res));
return 1;
}
curl = curl_easy_init();
if (curl) {
curl_easy_setopt(curl, CURLOPT_URL, "192.168.74.1");
curl_easy_setopt(curl, CURLOPT_POST, 1L);
curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_callback);
curl_easy_setopt(curl, CURLOPT_READDATA, &wt);
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
#ifdef USE_CHUNKED
{
struct curl_slist *chunk = NULL;
chunk = curl_slist_append(chunk, "Transfer-Encoding: chunked");
res = curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk);
}
#else
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long)wt.sizeleft);
#endif
#ifdef DISABLE_EXPECT
{
struct curl_slist *chunk = NULL;
chunk = curl_slist_append(chunk, "Expect:");
res = curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk);
}
#endif
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_global_cleanup();
return 0;
}
8. curl_formadd - 表单上传多个文件
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#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;
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);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_URL, url);
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;
}
9. curl_mime_data - 表单上传多个文件
#include <stdio.h>
#include <string.h>
#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);
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;
}
10. 使用多线程上传多个文件
#include <stdio.h>
#include "include/curl/curl.h"
#include <fcntl.h>
#include <sys/stat.h>
#include <Windows.h>
#include <process.h>
#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;
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);
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
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);
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++) {
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;
}
11. 请求下载文件
可以通过CURLOPT_PROGRESSFUNCTION设置下载进度显示
#include <iostream>
#include <stdio.h>
#include <Windows.h>
#include "./include/curl/curl.h"
#include "./include/curl/easy.h"
using namespace std;
size_t write_data(void *ptr, size_t size, size_t nmemb, void *stream) {
int written = fwrite(ptr, size, nmemb, (FILE *)stream);
return written;
}
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 *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, "http://www.newbiquge.com/modules/article/txtarticle.php?id=4486");
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);
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加速球看的。
12. 同时下载多个文件 - 无法实现保存到本地,只能实现下载效果
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include "include/curl/curl.h"
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_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;
}
13. 使用多线程请求下载多个文件
#include <iostream>
#include <stdio.h>
#include <Windows.h>
#include <process.h>
#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;
size_t write_data2(void *ptr, size_t size, size_t nmemb, void *stream) {
int written = fwrite(ptr, size, nmemb, (FILE *)stream);
return written;
}
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 *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, uf->urlArr);
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);
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];
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);
}
WaitForMultipleObjects(THREAD_COUNT, tHandles, TRUE, INFINITE);
printf("%d个文件已经下载完成!\n", THREAD_COUNT);
return 0;
}
三、总结
官方案例:https://curl.se/libcurl/c/example.html
这些案例都是在网上扒的和官网的案例,还有一些是自己写的,我只是将一些我觉得比较实用的例子记录下来!
|