|
|
@@ -1,21 +1,20 @@
|
|
|
#include "fileserver.h"
|
|
|
-
|
|
|
-static void run_http_server(FileServer *handle)
|
|
|
-{
|
|
|
- while (handle->isRunning())
|
|
|
- {
|
|
|
- handle->start();
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-FileServer::FileServer()
|
|
|
- : m_isRunning(false)
|
|
|
+#include "logger.h"
|
|
|
+#include <fstream>
|
|
|
+#include <QJsonObject>
|
|
|
+#include <QJsonDocument>
|
|
|
+#include <QDir>
|
|
|
+
|
|
|
+FileServer::FileServer(QObject *parent)
|
|
|
+ : QObject{parent}
|
|
|
{
|
|
|
+ connect(&m_thread, &QThread::started, this, &FileServer::run_hhttp_sever);
|
|
|
+ run("0.0.0.0", 18000);
|
|
|
}
|
|
|
|
|
|
FileServer::~FileServer()
|
|
|
{
|
|
|
- m_thread.join();
|
|
|
+ stop();
|
|
|
}
|
|
|
|
|
|
std::string FileServer::addr() const
|
|
|
@@ -30,58 +29,108 @@ uint16_t FileServer::port() const
|
|
|
|
|
|
bool FileServer::isRunning() const
|
|
|
{
|
|
|
- return m_isRunning;
|
|
|
-}
|
|
|
-
|
|
|
-void FileServer::start()
|
|
|
-{
|
|
|
- m_server.listen(m_addr, m_port);
|
|
|
+ return m_thread.isRunning();
|
|
|
}
|
|
|
|
|
|
void FileServer::run(const char *addr, unsigned short port)
|
|
|
{
|
|
|
m_addr = std::string(addr);
|
|
|
m_port = port;
|
|
|
- m_isRunning = true;
|
|
|
- m_thread = std::thread(run_http_server, this);
|
|
|
-
|
|
|
- // 上传接口
|
|
|
- m_server.Post("/upload", [&](const httplib::Request &req, httplib::Response &res)
|
|
|
- {
|
|
|
- if (!req.form.has_file("file")) {
|
|
|
- res.status = 400;
|
|
|
- res.set_content(R"({"error": "No file provided"})", "application/json");
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- const auto &file = req.form.get_file("file");
|
|
|
- std::cout << file.name << file.filename << std::endl;
|
|
|
-
|
|
|
- // auto it = req.form.files.find("file");
|
|
|
- // if (it == req.form.files.end())
|
|
|
- // {
|
|
|
- // res.status = 400;
|
|
|
- // res.set_content("No file field named 'file'", "text/plain");
|
|
|
- // return;
|
|
|
- // }
|
|
|
-
|
|
|
- // const httplib::MultipartFile &file = it->second;
|
|
|
-
|
|
|
- // std::string save_path = UPLOAD_DIR + "/" + file.filename;
|
|
|
-
|
|
|
- // if (!save_file(save_path, file.content)) {
|
|
|
- // res.status = 500;
|
|
|
- // res.set_content("Save failed", "text/plain");
|
|
|
- // return;
|
|
|
- // }
|
|
|
-
|
|
|
- // std::cout << "Uploaded: " << save_path << "\n";
|
|
|
-
|
|
|
- res.set_content("Upload OK", "text/plain"); });
|
|
|
+ LOG_DEBUG("file server start...");
|
|
|
+ m_thread.start();
|
|
|
}
|
|
|
|
|
|
void FileServer::stop()
|
|
|
{
|
|
|
- m_isRunning = false;
|
|
|
m_server.stop();
|
|
|
+ m_thread.quit();
|
|
|
+ m_thread.wait();
|
|
|
+}
|
|
|
+
|
|
|
+void FileServer::run_hhttp_sever()
|
|
|
+{
|
|
|
+
|
|
|
+ // 心跳
|
|
|
+ m_server.Get("/heartbeat", [&](const httplib::Request &req, httplib::Response &res) {
|
|
|
+ QJsonDocument doc;
|
|
|
+ QJsonObject obj = {
|
|
|
+ {"message", QString("Connected")}
|
|
|
+ };
|
|
|
+ doc.setObject(obj);
|
|
|
+
|
|
|
+ res.status = httplib::StatusCode::OK_200;
|
|
|
+ res.set_content(doc.toJson().data(), "application/json");
|
|
|
+ });
|
|
|
+
|
|
|
+ // 画面配置文件更新接口
|
|
|
+ m_server.Post("/update/monitor", [&](const httplib::Request &req, httplib::Response &res, const httplib::ContentReader &content_reader) {
|
|
|
+ if (req.is_multipart_form_data()) {
|
|
|
+ // NOTE: `content_reader` is blocking until every form data field is read
|
|
|
+ // This approach allows streaming processing of large files
|
|
|
+ std::vector<httplib::FormData> items;
|
|
|
+ QJsonDocument doc;
|
|
|
+ content_reader(
|
|
|
+ [&](const httplib::FormData &item) {
|
|
|
+ items.push_back(item);
|
|
|
+ return true;
|
|
|
+ },
|
|
|
+ [&](const char *data, size_t data_length) {
|
|
|
+ items.back().content.append(data, data_length);
|
|
|
+ return true;
|
|
|
+ });
|
|
|
+
|
|
|
+ // Process the received items
|
|
|
+ for (const auto& item : items) {
|
|
|
+ if (item.filename.empty()) {
|
|
|
+ // Text field
|
|
|
+ // std::cout << "Field: " << item.name << " = " << item.content << std::endl;
|
|
|
+
|
|
|
+ QJsonObject obj = {
|
|
|
+ {"message", QString("File error")}
|
|
|
+ };
|
|
|
+ doc.setObject(obj);
|
|
|
+
|
|
|
+ res.status = httplib::StatusCode::BadRequest_400;
|
|
|
+ res.set_content(doc.toJson().data(), "application/json");
|
|
|
+ } else {
|
|
|
+ // File
|
|
|
+ QString currentPath = QDir::currentPath();
|
|
|
+ QString savePath = QString("%1/%2").arg(currentPath, "update");
|
|
|
+
|
|
|
+ QDir dir(savePath);
|
|
|
+ if(!dir.exists()) {
|
|
|
+ dir.mkpath(savePath);
|
|
|
+ }
|
|
|
+
|
|
|
+ QString filename = QString("%1/%2").arg(savePath, "monitor.xml");
|
|
|
+ std::ofstream ofs(filename.toStdString(), std::ios::binary);
|
|
|
+ if (!ofs) {
|
|
|
+ LOG_ERROR("open file failed: {}", filename.toStdString());
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ ofs.write(item.content.data(), item.content.size());
|
|
|
+ ofs.close();
|
|
|
+ LOG_INFO("monitor configure file successfully update");
|
|
|
+ emit monitorConfigureUpdate();
|
|
|
+
|
|
|
+ QJsonObject obj = {
|
|
|
+ {"message", QString("'File successfully update")}
|
|
|
+ };
|
|
|
+ doc.setObject(obj);
|
|
|
+
|
|
|
+ res.status = httplib::StatusCode::OK_200;
|
|
|
+ res.set_content(doc.toJson().data(), "application/json");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ std::string body;
|
|
|
+ content_reader([&](const char *data, size_t data_length) {
|
|
|
+ body.append(data, data_length);
|
|
|
+ return true;
|
|
|
+ });
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ m_server.listen(m_addr, m_port);
|
|
|
}
|