【C++】使用cpp-httplib库实现http通讯

下载

GitHub:https://github.com/yhirose/cpp-httplib

仅需下载头文件httplib.h后导入至项目中即可,非常简单

服务端

现在以我的个人通讯录管理系统项目中的云端备份功能为例,简单的讲解这个库的用法

cpp文件头部

//server.cpp
#include <iostream>
#include "httplib.h"
using namespace std
​

上传

void upload_handler(const httplib::Request& req, httplib::Response& res) {
    //检查请求方法是否为 POST
    cout << "收到文件上传请求";
    if (req.method == "POST") {
        //获取上传文件的信息
        auto file = req.get_file_value("ContatcsDataText");
        //获取上传的文件名
        string original_filename = file.filename;
        //在这里你可以处理接收到的文本文件内容,并保存文件
        ofstream ofs(original_filename, ios::binary);
        ofs.write(file.content.c_str(), file.content.length());
        ofs.close();
        //返回上传成功的响应
        res.status = 200;
        res.set_content("文件上传成功!文件名:" + original_filename, "text/plain");
        cout << ",文件上传成功!文件名:" << original_filename << endl;
    }
    else {
        //返回不支持的请求方法的响应
        res.status = 405;
        res.set_content("不支持的请求方法", "text/plain");
        cout << ",文件上传失败!不支持的请求方法。" << endl;
    }
    return;
}
​

下载

void download_handler(const httplib::Request& req, httplib::Response& res) {
    cout << "收到文件下载请求";
    //从请求路径中获取文件名
    string path = req.path;
    string filename = path.substr(path.find_last_of("/") + 1);
    //读取文件内容
    ifstream file(filename, ios::binary);
    if (file.is_open()) {
        string content((istreambuf_iterator<char>(file)), istreambuf_iterator<char>());
        file.close();
        //设置响应头,指示文件下载
        res.set_header("Content-Disposition", "attachment; filename=" + filename);
        //设置响应内容和 Content-Type
        res.set_content(content, "application/octet-stream");
        res.status = 200;
        cout << ",已为客户传输文件,文件名:" << filename << endl;
    }
    else {
        //文件不存在或无法打开
        res.status = 404;
        cout << ",无法提供文件,文件未找到" << endl;
    }
    return;
}
​

删除

void remove_file(const httplib::Request& req, httplib::Response& res) {
    cout << "收到文件删除请求";
    //从请求路径中提取文件名
    string path = req.path;
    string filename = path.substr(path.find_last_of("/") + 1);
    //删除本地文件
    if (remove(filename.c_str()) == 0) {
        res.status = 200;
        res.set_content("文件删除成功", "text/plain");
        cout << ",文件删除成功,文件名:" << filename << endl;
    }
    else {
        res.status = 404;
        res.set_content("文件删除失败,文件可能不存在", "text/plain");
        cout << ",文件删除失败,文件名:" << filename << "可能不存在" << endl;
    }
    return;
}
​

main函数

int main() {
    //创建并配置 HTTP 服务器
    httplib::Server server;
    //处理 POST 请求的 "/upload" 路由
    server.Post("/upload", upload_handler);
    //处理 GET 请求的 "/download/*" 路由,* 表示通配符,用于捕获后续的路径部分
    server.Get(R"(/download/(.*))", [&](const httplib::Request& req, httplib::Response& res) {
        download_handler(req, res);
        });
    //处理 GET 请求的 "/remove/*" 路由,* 表示通配符,用于捕获后续的路径部分
    server.Get("/remove/(.*)", remove_file);
    //启动服务器并监听端口
    cout << "个人通讯录管理系统-服务器已启动,正在监听端口:19060" << endl;
    server.listen("0.0.0.0", 19060);
    return 0;
}
​

这个服务端有三个功能:①upload②download③remove。

在main函数中首先创建http服务器,然后链接三种请求路由(也就是上面的三个函数),然后让服务器监听特定的IP和端口。

客户端

上传

//保存当前用户数据至待备份文件
​
    //此处填写保存文件代码
​
//读取文本文件内容
ifstream file(filename.str());
string content((istreambuf_iterator<char>(file)), istreambuf_iterator<char>());
file.close();
​
//创建HTTP客户端
httplib::Client client("这里填写公网IP或域名", 19060);
//多形式数据集列表初始化
httplib::MultipartFormDataItems items = {
{"ContatcsDataText", content, filename.str(), "text/plain"}
};
//发送POST请求,将文本文件内容作为请求体发送给服务端
auto res = client.Post("/upload", items);
​
//检查响应状态码
if (res) {
    cout << "数据备份成功!" << endl;
    logsSave("将数据备份到了云端");
}
else {
    cout << "数据备份失败,错误代码:" << res.error() << endl;
}
//删除创建的备份文件,保证安全
remove(filename.str().c_str());

下载

//创建HTTP客户端
httplib::Client client("这里填写公网IP或域名", 19060);
//构建下载访问目录字符串
stringstream serverpath;
serverpath << "/download/" << filename.str();
//发送GET请求,从服务器下载文件
auto res2 = client.Get(serverpath.str());
//检查响应状态码
if (res2 && res2->status == 200) {
    //保存文件内容到本地
    ofstream ofs(filename.str(), ios::binary);
    ofs.write(res2->body.c_str(), res2->body.length());
    ofs.close();
}
else {
    cout << "暂无云端备份数据或无法连接到服务器。" << endl;
    Sleep(3000);
    return;
}
//先清空当前链表
clist.deleteAll();
//导入云端备份
​
    //这里写把保存的文件导入至客户端链表的操作
​
cout << "云端数据同步成功,本地数据已被覆盖" << endl;
saveNode(clist);
logsSave("将云端数据同步到了本地");
//删除下载的文件,保证安全
remove(filename.str().c_str());

删除

//删除云端部分
//预处理计算文件名
string username = currUser->getUsername();
encrype(username);
stringstream filename;
filename << username << ".txt";
//创建HTTP客户端
httplib::Client client("这里填写公网IP或域名", 19060);
stringstream serverpath;
serverpath << "/remove/" << filename.str();
//发送GET请求,删除服务器中的文件,目录例如/remove/114514.txt
auto res = client.Get(serverpath.str());

记得用stringstream创建对象,构建正确的文件名。

© 版权声明
THE END
点赞11 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容