微服務即時通信系統---(七)文件管理子服務

目錄

功能設計

模塊劃分

業務接口/功能示意圖

服務實現流程

服務代碼實現

封裝文件操作模塊(utils.hpp)

獲取唯一標識ID

文件讀操作

文件寫操作

編寫proto文件

文件元信息

文件管理proto

單文件上傳

多文件上傳

單文件下載

多文件下載

RPC調用

服務端創建子類(FileManageServiceImpl)完成RPC服務調用函數重寫

SingleFileUp(單文件上傳)

MultiFileUp(多文件上傳)

SingleFileDown(單文件下載)

MultiFileDown(多文件下載)

RPC服務端代碼(總)

服務端完成文件管理子服務類(FileManageServer)

注意

實例化服務類對象,啟動服務

工程系統構建配置文件(CMakeLists.txt)

服務測試


本章節,主要對項目中文件管理子服務模塊進行分析、開發與測試。

功能設計

文件管理子服務,主要提供兩個功能:文件的上傳和文件的下載,因此,文件管理子服務主要提供4個功能性接口:

1、單個文件的上傳:主要用于后臺,將收到的文件消息進行存儲。

2、多個文件的上傳:主要用于后臺,將收到的文件消息進行存儲。

3、單個文件的下載:在后臺用于獲取頭像文件數據,以及客戶端用于獲取文件數。

4、多個文件的下載:在后臺用于大批量獲取頭像文件數據,以及前端的批量文件下載。

模塊劃分

參數/配置文件解析模塊基于gflags框架直接使用,進行參數/配置文件的解析。
日志模塊基于spdlog封裝的logger 直接進行日志輸出。
服務注冊模塊基于etcd框架封裝的注冊模塊 直接進行文件管理子服務模塊的服務注冊。
RPC服務模塊基于brpc框架 搭建文件管理子服務的RPC服務器。
文件操作模塊基于標準庫的文件流操作實現文件的讀寫封裝,用于文件操作。

業務接口/功能示意圖

文件上傳:

文件下載/獲取:

服務實現流程

1、實現文件操作模塊的封裝(utils.hpp),其中包括 文件讀操作、文件寫操作,外加一個獲取唯一標識ID的操作(用于用戶ID、文件ID等)。
2、編寫服務所需的proto文件,利用protoc工具生成RPC服務器所需的.pb.h 和 .pb.cc 項目文件。
3、服務端 創建子類,繼承于proto文件中RPC調用類,并進行功能性接口函數重寫。
4、服務端 完成文件管理子服務類。
5、實例化 服務類對象,啟動服務。

服務代碼實現

封裝文件操作模塊(utils.hpp)

獲取唯一標識ID

在代碼中,文件ID、用戶ID 或者是 會話ID 都由此處操作來獲取。

這里使用16個隨機的字符串 組成這個唯一的標識ID。

實現思想:

1、先生成6個 0 ~ 255 內的隨機數字,而1 個 字節,為 8位。再將這8位,分成4 4 位,每4位轉換成1個16進制數字,從而 1個隨機數字 轉換成 2個 16位數字。至此,得到12 位 隨機16進制字符。

2、再通過一個 靜態變量,生成一個2 字節的 編號數字,同樣 轉換成 4 個 16位數字。至此,得到4位 隨機16進制字符。

3、將1和2進行拼接,得到16個隨機的字符串。

utils.hpp:

    // 生成一個唯一標識IDstd::string uuid(){// 1. 生成12位16進制字符std::random_device rd;                                   // 實例化設備隨機數對象, 用于生成設備隨機數(唯一性更強)std::mt19937 generator(rd());                            // 以設備隨機數為種子, 實例化隨機數對象(mt19937:一種生成隨機數的方式)std::uniform_int_distribution<int> distribution(0, 255); // 限定生成隨機數的范圍std::stringstream ss;for (int i = 0; i < 6; ++i){if (i == 2)ss << "-"; // 添加-, 最終形式為: xxxx-yyyy-zzzz-ddddss << std::setw(2) << std::setfill('0') << std::hex << distribution(generator);// distribution(generator) : 生成一個 0-255的隨機數// std::hex + std::setw(2) : 轉換為 2個 16進制數// std::setfill('0'): 不足的,前面用0填充}// 2. 通過靜態變量生成 4位 16進制字符ss << "-";static std::atomic<short> idx(0);short tmp = idx.fetch_add(1);ss << std::setw(4) << std::setfill('0') << std::hex << tmp;return ss.str();}

文件讀操作

通過傳入文件名 和 承接文件內容的string,用來獲取文件內容。

實現思想:

1、根據文件名打開文件。

2、跳轉文件內部指針,獲取文件指針偏移量(文件大小)。

3、再將文件內部指針跳轉開頭,進行讀取文件內容。

4、關閉文件。

utils.hpp:

    // 讀取文件bool ReadFile(const std::string &file_name, std::string &body){std::ifstream ifs(file_name, std::ios::in | std::ios::binary);if (ifs.is_open() == false){LOG_ERROR("打開文件失敗, file_name: {}", file_name);return false;}ifs.seekg(0, std::ios::end);size_t file_size = ifs.tellg();ifs.seekg(0, std::ios::beg);body.resize(file_size);ifs.read(&body[0], file_size);if (ifs.good() == false){LOG_ERROR("讀取文件失敗, file_name: {}", file_name);ifs.close();return false;}ifs.close();return true;}

文件寫操作

通過傳入文件名 和 想要寫入的內容,用來向文件寫入數據。

實現思想:

1、根據文件名打開文件。

2、寫入數據。

3、關閉文件。

utils.hpp:

    // 寫入文件bool WriteFile(const std::string &file_name, const std::string &body){std::ofstream ofs(file_name, std::ios::out | std::ios::binary | std::ios::trunc); // 覆蓋式寫入if (ofs.is_open() == false){LOG_ERROR("打開文件失敗, file_name: {}", file_name);return false;}ofs.write(body.c_str(), body.size());if (ofs.good() == false){LOG_ERROR("寫入文件失敗, file_name: {}", file_name);ofs.close();return false;}ofs.close();return true;}

編寫proto文件

文件元信息

首先對于文件來說,不光需要編寫文件的上傳/下載的proto文件,文件還需要有它的元信息(文件ID、文件名稱、文件大小、文件內容),并且后續用戶發送的消息里面,也可能是文件,需要我們進行識別,所以將文件的元信息,單獨放在一個proto文件里面(后續用戶元信息、會話元信息、圖像元信息、語音元信息、字符串消息元信息都放在里面)。統稱為 base.proto

文件元信息(FileInfo)成員:

1、file_id:文件ID。

2、file_size:文件大小。

3、file_name:文件名稱。

4、file_content:文件內容。

// ------文件元信息------
message FileInfo
{optional string file_id = 1;optional int64 file_size = 2;optional string file_name = 3;optional bytes file_content = 4;
};

考慮到多文件上傳/下載需要repeated的相同信息,所以將文件的上傳和下載所需要的信息也放進來。 

// ------文件元信息 + 文件上傳/下載信息------
message FileInfo
{optional string file_id = 1;optional int64 file_size = 2;optional string file_name = 3;optional bytes file_content = 4;
};
message FileUpInfo
{string file_name = 1;int64 file_size = 2;bytes file_content = 3;
};
message FileDownInfo
{string file_id = 1;bytes file_content = 2;
};

文件管理proto

既然文件管理模塊有4個功能性接口,那么就有4個對應的請求與響應結構,以及最終的PRC調用(fileManage.proto)。

單文件上傳

SingleFileUpReq包含成員:

1、請求ID:標識請求的唯一性。

2、文件上傳信息:存儲文件上傳所需信息(文件名、文件大小、文件內容)。

3、用戶ID(optional):標明來自哪個用戶。

4、會話ID(optional):標明來自哪個會話。

SingleFileUpResp包含成員:

1、請求ID:對應請求中的請求ID,標識請求唯一性。

2、成功標識:標識該次請求的處理結果。

3、錯誤信息(optional):如果處理出錯,記錄出錯信息。

4、文件元信息:存儲文件元信息(文件ID、文件大小、文件名、文件內容)。

// ------單文件上傳------
message SingleFileUpReq
{string req_id = 1;FileUpInfo file_up_info = 2;optional string user_id = 3;optional string session_id = 4;
};
message SingleFileUpResp
{string req_id = 1;bool success = 2;optional string err_msg = 3;optional FileInfo file_info = 4;
};
多文件上傳

多文件上傳和單文件上傳沒啥不同的,就是里面的文件東西,由列表來構成。

// ------多文件上傳------
message MultiFileUpReq
{string req_id = 1;repeated FileUpInfo file_up_info_list = 2;optional string user_id = 3;optional string session_id = 4;
};
message MultiFileUpResp
{string req_id = 1;bool success = 2;optional string err_msg = 3;repeated FileInfo file_info_list = 4;
};
單文件下載

SingleFileDownReq包含成員:

1、請求ID:標識請求的唯一性。

2、文件ID:根據文件ID才能找到文件。

3、用戶ID(optional):標明來自哪個用戶。

4、會話ID(optional):標明來自哪個會話。

SingleFileDownResp包含成員:

1、請求ID:對應請求中的請求ID,標識請求唯一性。

2、成功標識:標識該次請求的處理結果。

3、錯誤信息(optional):如果處理出錯,記錄出錯信息。

4、文件下載信息:存儲文

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/71025.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/71025.shtml
英文地址,請注明出處:http://en.pswp.cn/web/71025.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

fluent-ffmpeg 依賴詳解

fluent-ffmpeg 是一個用于在 Node.js 環境中與 FFmpeg 進行交互的強大庫&#xff0c;它提供了流暢的 API 來執行各種音視頻處理任務&#xff0c;如轉碼、剪輯、合并等。 一、安裝 npm install fluent-ffmpeg二、基本使用 要使用 fluent-ffmpeg&#xff0c;首先需要確保系統中…

第16天:C++多線程完全指南 - 從基礎到現代并發編程

第16天&#xff1a;C多線程完全指南 - 從基礎到現代并發編程 一、多線程基礎概念 1. 線程創建與管理&#xff08;C11&#xff09; #include <iostream> #include <thread>void hello() {std::cout << "Hello from thread " << std::this_…

Pwntools 的詳細介紹、安裝指南、配置說明

Pwntools&#xff1a;Python 開源安全工具箱 一、Pwntools 簡介 Pwntools 是一個由 Security researcher 開發的 高效 Python 工具庫&#xff0c;專為密碼學研究、漏洞利用、協議分析和逆向工程設計。它集成了數百個底層工具的功能&#xff0c;提供統一的 Python API 接口&am…

ES的簡單講解

功能 &#xff1a; 文檔存儲 與 文檔搜索 特點&#xff1a;比如有一個文檔名 “你好” 可以用‘你‘&#xff0c;好&#xff0c;你好都可以搜索到這個文檔 ES核心概念 類似于數據庫中表的概念&#xff0c;在表的概念下又對數據集合進行了細分 ? ES_Client查詢接口 cpr::R…

leetcode_字典樹 139. 單詞拆分

139. 單詞拆分 給你一個字符串 s 和一個字符串列表 wordDict 作為字典。如果可以利用字典中出現的一個或多個單詞拼接出 s 則返回 true。 注意&#xff1a;不要求字典中出現的單詞全部都使用&#xff0c;并且字典中的單詞可以重復使用。 思路: 定義狀態&#xff1a; 設dp[i]表…

寶塔安裝向量數據庫-Milvus

注&#xff1a;寶塔需要安裝好docker容器組件&#xff01; 1、純血寶塔安裝 1.1 在線上鏡像中&#xff0c;拉取milvus鏡像&#xff0c;創建milvus容器 1.2 安裝milvus管理工具ATTU&#xff1b;同樣方式拉取線上鏡像創建attu容器 2、自定義安裝 2.1修改配置 {"registry-…

【K8S】Kubernetes 基本架構、節點類型及運行流程詳解(附架構圖及流程圖)

Kubernetes 架構 k8s 集群 多個 master node 多個 work nodeMaster 節點&#xff08;主節點&#xff09;&#xff1a;負責集群的管理任務&#xff0c;包括調度容器、維護集群狀態、監控集群、管理服務發現等。Worker 節點&#xff08;工作節點&#xff09;&#xff1a;實際運…

數據庫MySQL,在終端輸入后,提示不是內部命令等

【解決問題】mysql提示不是內部或外部命令&#xff0c;也不是可運行的程序 一般這種問題是因為沒有在系統變量里面添加MySQL的可執行路徑 以下是添加可執行路徑的方法&#xff1a; 第一步&#xff1a;winR輸入services.msc 然后找到MySQL&#xff0c;右擊屬性并復制MySQL的可執…

Python 中的線程模塊

Python 中的線程模塊 Python 中的線程模塊 Python 中的線程模塊 thread 模塊是一個標準模塊&#xff0c;提供了簡單易用的方法為程序構建多線程。在幕后&#xff0c;該模塊使用較低級的 _thread 模塊&#xff0c;在 Python 早期版本中&#xff0c;該模塊是多線程的流行選擇。 …

PhotoShop學習01

了解Photoshop 這里省略了Photoshop的軟件安裝&#xff0c;請自行查找資源下載。 1.打開圖片 下圖為啟動photoshop后出現的界面&#xff0c;我們可以通過創建新文件或打開已有文件來啟用photoshop的工作界面。 可以通過左邊的按鈕進行新文件的創建或打開已有文件。 也可以點…

Python大戰Java:AI時代的編程語言‘復仇者聯盟‘能否換C位?

背景 當Java程序員在咖啡機前念叨’Python憑什么搶我飯碗’時&#xff0c;AI實驗室里的Python工程師正用5行代碼召喚出神經網絡——這場編程語言的’權力的游戲’&#xff0c;勝負可能比你想象的更魔幻&#xff01;" 一、茶水間里的戰爭&#xff1a;Java和Python的相愛相…

GitCode 助力 python-office:開啟 Python 自動化辦公新生態

項目倉庫&#xff1a;https://gitcode.com/CoderWanFeng1/python-office 源于需求洞察&#xff0c;打造 Python 辦公神器 項目作者程序員晚楓在運營擁有 14w 粉絲的 B 站賬號 “Python 自動化辦公社區” 時&#xff0c;敏銳察覺到非程序員群體對 Python 學習的強烈需求。在數字…

javaweb + AI day03

一、web基礎 二、分層解耦 注意&#xff1a;bean的名字默認是類名的首字母小寫&#xff01;&#xff01;&#xff01; 三、Mysql count不參與null值統計 四、JDBC 五、MyBatis 數據庫連接池

運行程序時出現加載配置文件時出錯,對路徑****的訪問被拒絕

問題&#xff1a;最近給客戶用c#語言編寫進銷存項目&#xff0c;在用vs2022自帶的打包工具Microsoft visual studio installer projects 打包生成了安裝文件&#xff0c;順利安裝后&#xff0c;點擊桌面快捷方式后出現如下錯誤 經過查詢相關資料發現是桌面快捷方式的權限問題&a…

基于C#的CANoe CLR Adapter開發指南

一、引言 CANoe 是一款廣泛應用于汽車電子開發和測試的工具&#xff0c;它支持多種編程接口&#xff0c;方便開發者進行自定義擴展。CANoe CLR Adapter 允許我們使用 C# 語言與 CANoe 進行交互&#xff0c;充分利用 C# 的強大功能和豐富的類庫。本文將詳細介紹如何基于 C# 進行…

conda怎么遷移之前下載的環境包,把python從3.9升級到3.10

克隆舊環境&#xff08;保留舊環境作為備份&#xff09; conda create -n cloned_env --clone old_env 在克隆環境中直接升級 Python conda activate cloned_env conda install python3.10 升級 Python 后出現 所有包導入失敗 的問題&#xff0c;通常是因為依賴包與新 Pyth…

一文掌握 Scrapy 框架的詳細使用,包括實戰案例

更多內容請見: 爬蟲和逆向教程-專欄介紹和目錄 文章目錄 1. Scrapy 簡介2. Scrapy 的核心組件3. 安裝 Scrapy4. 創建 Scrapy 項目4.1 創建項目4.2 創建 Spider5. 編寫 Spider5.1 定義 Item5.2 編寫 Spider 邏輯6. 運行 Scrapy 爬蟲6.1 運行爬蟲6.2 保存爬取數據7. Scrapy 的高…

筆試-查找最長公共字符串

應用 以字符串形式給定兩行代碼&#xff0c;1<長度<100&#xff0c;由字母、數字、空格組成。請找出最長公共子字符串&#xff0c;如果不存在返回空字符串。 實現 str1 input("請輸入字符串1&#xff1a;") str2 input("請輸入字符串2&#xff1a;&q…

【三維分割】LangSplat: 3D Language Gaussian Splatting(CVPR 2024 highlight)

論文&#xff1a;https://arxiv.org/pdf/2312.16084 代碼&#xff1a;https://github.com/minghanqin/LangSplat 文章目錄 一、3D language field二、回顧 Language Fields的挑戰三、使用SAM學習層次結構語義四、Language Fields 的 3DGS五、開放詞匯查詢&#xff08;Open-voca…

haclon固定相機位標定

什么是標定&#xff1f; 工業應用中相機拍到一個mark點的坐標為C1&#xff08;Cx,Cy&#xff09;&#xff0c;C1點對應的龍門架/機械手等執行端對應的坐標是多少&#xff1f; 標定就是解決這個問題&#xff0c;如相機拍到一個點坐標C1&#xff08;Cx,Cy&#xff09;&#xff0c…