一、http数据发送

1、先将图片转换为base64格式

std::string detectNet::Mat2Base64(const cv::Mat &image, std::string imgType){
    std::vector<uchar> buf;
    cv::imencode(imgType, image, buf);
    //uchar *enc_msg = reinterpret_cast<unsigned char*>(buf.data());
    std::string img_data = base64_encode(buf.data(), buf.size(), false);
    return img_data;
}

2、将数据以json格式进行发送

void detectNet::send_json_people(cv::Mat img, std::string label, std::string level, std::string rtsp){
    std::string out = Mat2Base64(img,".jpg");
    //std::cout << out << std::endl;

    ImgInfo imgInfo(out, label, level, rtsp);
    static auto client = httplib::Client("127.0.0.1", 18080);
    auto result = client.Post("/uploadAlgorithmResult", imgInfo.to_json_people(), "application/json");
    if (result != nullptr && result->status == 200) {
        std::cout << result->body << std::endl;
    }
}

其中 ImgInfo 类为:

#ifndef HTTP_DEMO_IMGINFO_H
#define HTTP_DEMO_IMGINFO_H

#include <utility>

#include "cJSON.h"
#include "base64.h"


#define RTSP_URL "rtsp://admin:a123456789@192.168.8.31:554/h264/ch1/main/av_stream/1"
#define AlgorithmType "hook_detection"
#define AlgorithmType_people "danger_zone"
#define AlgorithmType_crooked "crooked"

class ImgInfo {
private:
    std::string img;
    std::string label;
    std::string rtsp;
    std::string level;
public:
    ImgInfo(std::string img, std::string label, 
            std::string level, std::string rtsp) : img(std::move(img)), label(std::move(label)),
                                 level(std::move(level)), rtsp(std::move(rtsp)) {}

    std::string to_json_people() {
        auto *root = cJSON_CreateObject();
        cJSON_AddStringToObject(root, "image", img.c_str());
        cJSON_AddStringToObject(root, "level", level.c_str());
        cJSON_AddStringToObject(root, "rtsp", rtsp.c_str());
        cJSON_AddStringToObject(root, "type", AlgorithmType_people);
        cJSON_AddStringToObject(root, "label", label.c_str());


        /*
        cJSON *label_array = cJSON_CreateArray();
        for (auto &i: label) {
            cJSON_AddItemToArray(label_array, cJSON_CreateString(i.c_str()));
        }
        cJSON_AddItemToObject(root, "label", label_array);
        */
        char *out = cJSON_Print(root);
        std::string res = out;
        free(out);
        cJSON_Delete(root);
        return res;
    }
};

#endif //HTTP_DEMO_IMGINFO_H

上述代码中json数据有五个部分:image为图片数据,level是告警等级,rtsp为数据流地址,type是算法类型,label是算法标签等,所以数据发送为这五个内容。

二、http数据接收

HttpServer.cpp如下: 

//#include <QFile>
//#include <FileUtils.hpp>
#include "HttpServer.h"
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
//#include "QString"
//#include "TimeUtils.hpp"
//#include "AlgorithmCommon.h"
//#include "QJsonObject"
//#include "QJsonDocument"
//#include "QJsonArray"
//#include "httplib.h"

//#include "log.h"
//#include "cJSON.h"

HttpServer::HttpServer(std::string ip, int port) : server_ip(ip), server_port(port) {

    //event_handler = new AlgorithmAlarmHandler();

}

HttpServer::~HttpServer() {
    stopListen();
    if (read_thd.joinable()) {
        read_thd.join();
    }
}

void HttpServer::startListen() {
    read_thd = std::thread([=]() {
        serverListen();
    });
    //event_handler->startHandlerThread();
}

void HttpServer::stopListen() {
    if (server.is_running()) {
        server.stop();
    }
}

void HttpServer::serverListen() {
    if (!server.is_valid()) {
        std::cout << "http server invalid" << std::endl;
        return;
    }

    // 服务器状态
    server.Get("/server/status", [&](const Request &req, Response &res) {
        onServerStatus(req, res);
    });

    // 上传算法结果
    server.Post("/uploadAlgorithmResult", [&](const Request &req, Response &res) {
        onUploadAlgorithmResult(req, res);
    });


    // 错误处理
    server.set_error_handler([&](const Request &req, Response &res) {
        onErrorHandle(req, res);
    });

    //qDebug() << "server start listen";
    server.listen(server_ip.c_str(), server_port);
}

void HttpServer::onServerStatus(const httplib::Request &req, httplib::Response &res) {
    res.body = R"({"code": 200,"msg": "Server is already Running"})";
}

void HttpServer::onUploadAlgorithmResult(const httplib::Request &req, httplib::Response &res) {
    std::string content_type = httputillib::GetContentType(req.headers);
    //if (content_type != "application/json") {
   //     qDebug() << "contentType 异常, content_type:" << QString::fromStdString(content_type);
    //}
    bool parseRet = parseAlgorithmResult(req.body);
	//bool parseRet = true;
    std::string rspMsg;
    if (parseRet) {
        rspMsg = std::string(R"({"msg":"Recv Success, Parse Success."})");
    } else {
        rspMsg = std::string(R"({"msg":"Recv Success, Parse Failed."})");
    }
    res.body = std::move(rspMsg);
}


// 错误请求处理
void HttpServer::onErrorHandle(const httplib::Request &req, httplib::Response &res) {
    const char *fmt = {"\"error\": \"服务器不支持该方法\""};
    char buf[BUFSIZ] = {0};
    snprintf(buf, sizeof(buf), fmt, res.status);

    res.set_content(buf, "application/json");
}


bool HttpServer::parseAlgorithmResult(const std::string &body) {

    //std::cout << "body:" << body << std::endl;
	Json::Reader reader;
	Json::Value root;
    //std::ifstream in(body, std::ios::binary);
    //if (!in.is_open()) {
    //    std::cout << "open file failed" << std::endl;
    //    return false;
    //}
    if (!reader.parse(body, root)) {
        std::cout << "parse failed" << std::endl;
        return false;
    }
    std::string rtsp = root["rtsp"].asString();
    std::cout << "rtsp:" << rtsp << std::endl;
    std::string level = root["level"].asString();
    std::cout << "level:" << level << std::endl;
    std::string type = root["type"].asString();
    std::cout << "type:" << type << std::endl;
	std::string image = root["image"].asString();
    //std::cout << "image:" << image << std::endl;
	std::string out = base64_decode(image);
    std::string decoded_jpeg = std::move(out);
    //std::cout << "decoded_jpeg: " << decoded_jpeg << std::endl;

	cv::Mat mat2(1, decoded_jpeg.size(), CV_8U, (char*)decoded_jpeg.data());
    cv::Mat dst = cv::imdecode(mat2, CV_LOAD_IMAGE_COLOR);
	cv::imwrite(rtsp.substr(1) + ".jpg", dst);  

    return true;
}

 HttpServer.h如下:

//#ifndef CPPHTTPSERVER_HTTPSERVER_H
//#define CPPHTTPSERVER_HTTPSERVER_H

#include "httputillib.h"
#include "httplib.h"
#include "base64.h"
//#include "thread"
#include <thread>
#include <time.h>

#include <json.h>


class HttpServer{
public:
    HttpServer(std::string ip, int port);
    ~HttpServer();

    void startListen();

    void stopListen();

private:

    void serverListen();

    // 回调函数: 错误请求处理
    void onErrorHandle(const httplib::Request &req, httplib::Response &res);

    // 回调函数: 获取服务器状态
    void onServerStatus(const httplib::Request &req, httplib::Response &res);

    // 回调函数: 上传算法结果
    void onUploadAlgorithmResult(const httplib::Request &req, httplib::Response &res);

    // 回调函数:处理算法数据
    bool parseAlgorithmResult(const std::string &body);

    std::string server_ip;
    int server_port;

    Server server;
    std::thread read_thd;

};

//#endif //CPPHTTPLIB_HTTPLIB_H

httputillib.h如下:

#include <httplib.h>

using namespace httplib;


namespace httputillib {
// 打印请求头
static std::string DumpHeaders(const Headers &headers) {
	std::string s;
	char buf[BUFSIZ] = {0};

	for (auto it = headers.begin(); it != headers.end(); ++it) {
		const auto &x = *it;
		snprintf(buf, sizeof(buf), "%s: %s\n", x.first.c_str(), x.second.c_str());
		s += buf;
	}

	return s;
}

// 从请求同获取content type
static std::string GetContentType(const httplib::Headers &headers) {
	auto iter = headers.find("Content-Type");
	if (iter == headers.end()) {
		return std::string();
	}

	return iter->second;
}

};

上述完整代码可详见github或者百度网盘

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐