فهرست منبع

update fileserver (monitor configure)

xuqiang 4 ماه پیش
والد
کامیت
90f6beab0d
3فایلهای تغییر یافته به همراه119 افزوده شده و 61 حذف شده
  1. 2 0
      include/appcontext.h
  2. 13 6
      include/fileserver.h
  3. 104 55
      src/fileserver.cpp

+ 2 - 0
include/appcontext.h

@@ -6,6 +6,7 @@
 #include "projectmanager.h"
 #include "network.h"
 #include "serialport.h"
+#include "fileserver.h"
 
 class AppContext : public QObject
 {
@@ -26,6 +27,7 @@ private:
     ProjectManager m_projectMgr;
     Network m_network;
     SerialPort m_serialPort;
+    FileServer m_fileServer;
 
 };
 

+ 13 - 6
include/fileserver.h

@@ -1,30 +1,37 @@
 #ifndef __FILESERVER_H__
 #define __FILESERVER_H__
 
+#include <QObject>
 #include <httplib.h>
 #include <stdint.h>
-#include <thread>
+#include <QThread>
 
-class FileServer
+class FileServer : public QObject
 {
+    Q_OBJECT
 
 public:
-    explicit FileServer();
+    explicit FileServer(QObject *parent = nullptr);
     ~FileServer();
 
     std::string addr() const;
     uint16_t port() const;
     bool isRunning() const;
     void run(const char *addr, unsigned short port);
-    void start();
     void stop();
 
 private:
     std::string m_addr;
     uint16_t m_port;
-    bool m_isRunning;
-    std::thread m_thread;
     httplib::Server m_server;
+    QThread m_thread;
+
+signals:
+    void monitorConfigureUpdate();
+
+private slots:
+    void run_hhttp_sever();
+
 };
 
 #endif // FILESERVER_H

+ 104 - 55
src/fileserver.cpp

@@ -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);
 }