IM项目-----文件管理子服务

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 前言
  • 一、搭建思想
  • 二、服务器搭建
    • 1.继承fileService类,重写业务方法
    • 服务器类设计
    • 建造者类


前言

文件管理子服务,主要用于管理用户的头像,以及消息中的文件存储,因此需要提供
以下接口:

  1. 文件的上传
    a. 单个文件的上传:这个接口基本用于后台部分,收到文件消息后将文件数据
    转发给文件子服务进行存储
    b. 多个文件的上传:这个接口基本用于后台部分,收到文件消息后将文件数据
    转发给文件子服务进行存储
  2. 文件的下载
    a. 单个文件的下载:在后台用于获取用户头像文件数据,以及客户端用于获取
    文件/语音/图片消息的文件数据
    b. 多个文件的下载:在后台用于大批量获取用户头像数据(比如获取用户列表
    的时候),以及前端的批量文件下载
//获取单个文件请求
message GetSingleFileReq {string request_id = 1;string file_id = 2;optional string user_id = 3;optional string session_id = 4;
}//获取单个文件响应
message GetSingleFileRsp {string request_id = 1;bool success = 2;optional string errmsg = 3;optional FileDownloadData file_data = 4;
}message GetMultiFileReq {string request_id = 1;optional string user_id = 2;optional string session_id = 3;repeated string file_id_list = 4;
}message GetMultiFileRsp {string request_id = 1;bool success = 2;optional string errmsg = 3;map<string, FileDownloadData> file_data = 4;
}message PutSingleFileReq {string request_id = 1;optional string user_id = 2;optional string session_id = 3;FileUploadData file_data = 4;
}message PutSingleFileRsp {string request_id = 1;bool success = 2;optional string errmsg = 3;optional FileMessageInfo file_info = 4;
}message PutMultiFileReq {string request_id = 1;optional string user_id = 2;optional string session_id = 3;repeated FileUploadData file_data = 4;
}message PutMultiFileRsp {string request_id = 1;bool success = 2;string errmsg = 3;repeated FileMessageInfo file_info = 4;
}rpc服务
service FileService {rpc GetSingleFile(GetSingleFileReq) returns (GetSingleFileRsp);rpc GetMultiFile(GetMultiFileReq) returns (GetMultiFileRsp);rpc PutSingleFile(PutSingleFileReq) returns (PutSingleFileRsp);rpc PutMultiFile(PutMultiFileReq) returns (PutMultiFileRsp);
}

一、搭建思想

文件管理子服务和语音管理子服务基本一致,他们都有服务注册,rpc服务器.
唯一不同的是文件管理子服务中的rpc服务是进行文件的读写。
我们通过标准库的文件读写类进行一个文件的读写。
针对文件的上传,我们需要给文件生成一个uuid,这个uuid就作为文件的名称在服务器进行文件的写入。然后在resp中设置进生成的uuid。
针对文件的下载,调用端只需要提供一个文件id,也就是我们生成的uuid,服务端就可以找到对应的文件了。

在这里插入图片描述

二、服务器搭建

1.继承fileService类,重写业务方法

文件管理子服务提供了四个功能。单个文件的上传下载,多个文件的上传下载。
针对上传:首先为该文件生成一个uuid,然后进行进行文件内容的写入。最后返回文件Id(uuid)。
针对下载:首先获取文件ID,然后找到文件进行文件内容的读取,最后返回文件内容。

只有一个地方需要注意,就是该类有一个成员变量std::string _storage_path。
我们的文件都是存贮在这个路径下的,所以当我们进行文件的写入和读取时,都需要先在文件id的前面拼接上这个路径。

//1.继承文件服务类,重写业务方法class FileServiceImpl : public FileService{public:FileServiceImpl(const std::string& path):_storage_path(path){umask(0);if(_storage_path.back() != '/') _storage_path += "/";mkdir(_storage_path.c_str(), 0775);}~FileServiceImpl(){}//获取单个文件void GetSingleFile(google::protobuf::RpcController* controller,const ::lkm_im::GetSingleFileReq* request,::lkm_im::GetSingleFileRsp* response,::google::protobuf::Closure* done){brpc::ClosureGuard rpc_guard(done);response->set_request_id(request->request_id());//获取文件ID std::string file_id = request->file_id();std::string file_name = _storage_path + file_id;//读取文件内容std::string body;bool ret = readFile(file_name,body);if(!ret){LOG_ERROR("{},获取单个文件失败",request->request_id());response->set_success(false);response->set_errmsg("读取文件数据失败");return;}//组织响应response->set_success(true);response->mutable_file_data()->set_file_id(request->file_id());response->mutable_file_data()->set_file_content(body);}//获取多个文件void GetMultiFile(google::protobuf::RpcController* controller,const ::lkm_im::GetMultiFileReq* request,::lkm_im::GetMultiFileRsp* response,::google::protobuf::Closure* done){brpc::ClosureGuard rpc_guard(done);response->set_request_id(request->request_id());//循环处理多个文件for (int i = 0; i < request->file_id_list_size(); i++){//获取文件ID (文件名)std::string file_id = request->file_id_list(i);std::string file_name = _storage_path + file_id;//读取文件内容std::string body;bool ret = readFile(file_name,body);if(!ret){LOG_ERROR("{},获取多个文件失败",request->request_id());response->set_success(false);response->set_errmsg("读取文件数据失败");return;}//组织响应FileDownloadData fileDownloadData;fileDownloadData.set_file_id(file_id);fileDownloadData.set_file_content(body);response->mutable_file_data()->insert({file_id,fileDownloadData});}response->set_success(true);}//上传单个文件void PutSingleFile(google::protobuf::RpcController* controller,const ::lkm_im::PutSingleFileReq* request,::lkm_im::PutSingleFileRsp* response,::google::protobuf::Closure* done){brpc::ClosureGuard rpc_guard(done);response->set_request_id(request->request_id());//为文件生成一个uuidstd::string fid = uuid();std::string file_name = _storage_path + fid;    //文件实际存储路径//获取文件内容std::string file_content = request->file_data().file_content();//将内容写入文件int ret = writeFile(file_name,file_content);if(!ret){LOG_ERROR("{},上传单个文件失败",request->request_id());response->set_success(false);response->set_errmsg("写入文件数据失败");return;}//组织响应  给客户端返回我们生成的文件ID就行response->mutable_file_info()->set_file_id(fid);response->mutable_file_info()->set_file_size(request->file_data().file_size());response->mutable_file_info()->set_file_name(request->file_data().file_name());response->set_success(true);}//上传多个文件void PutMultiFile(google::protobuf::RpcController* controller,const ::lkm_im::PutMultiFileReq* request,::lkm_im::PutMultiFileRsp* response,::google::protobuf::Closure* done){brpc::ClosureGuard rpc_guard(done);response->set_request_id(request->request_id());for(int i = 0; i < request->file_data_size(); i++){//为文件生成一个uuidstd::string fid = uuid();std::string file_name = _storage_path + fid;//获取文件内容std::string file_content = request->file_data(i).file_content();//将内容写入文件int ret = writeFile(file_name,file_content);if(!ret){LOG_ERROR("{},上传多个文件失败",request->request_id());response->set_success(false);response->set_errmsg("写入文件数据失败");return;}//组织响应  给客户端返回我们生成的文件ID就行lkm_im::FileMessageInfo * fileMessageInfo = response->add_file_info();fileMessageInfo->set_file_id(fid);fileMessageInfo->set_file_name(request->file_data(i).file_name());fileMessageInfo->set_file_size(request->file_data(i).file_size());}response->set_success(true);}private:std::string _storage_path;   //存储文件路径};

服务器类设计

和语音识别子服务一样,这里也采用了建造者模式。但是我们的文件管理子服务只有两个对象,一个rpc服务器,一个服务注册对象。

//2.文件存储管理子服务服务器编写class FileServer{public:using ptr = std::shared_ptr<FileServer>;FileServer(const Registry::ptr& registry,const std::shared_ptr<brpc::Server>& server):_registry(registry),_server(server){}~FileServer(){}//启动rpc服务器void start(){_server->RunUntilAskedToQuit();}private:Registry::ptr _registry;    //服务注册对象std::shared_ptr<brpc::Server> _server;  //rpc服务器};

建造者类

在构造rpc服务器时需要传入一个路径,因为这里需要为rpc服务器添加服务,需要构造fileServiceImpl对象,这个对象需要传入一个path存储路径。

//3.文件存储管理子服务构造者class FileServerBuild{public:void make_registry(const std::string& etcd_host,const std::string& service_name,const std::string& service_host){_registry = std::make_shared<Registry>(etcd_host);//进行服务注册_registry->registry(service_name,service_host);}void make_brpc(uint16_t port,uint32_t timeout = -1,uint8_t num_threads = 1,const std::string& path = "./data/"){//创建brpc服务器对象_server = std::make_shared<brpc::Server>();//添加服务FileServiceImpl *FileService = new FileServiceImpl(path);    //把这个对象的交给_server释放int ret = _server->AddService(FileService,brpc::ServiceOwnership::SERVER_OWNS_SERVICE);if (ret == -1) {LOG_ERROR("添加rpc服务失败");abort();}brpc::ServerOptions options;options.idle_timeout_sec = timeout;options.num_threads = num_threads;ret = _server->Start(port,&options);if(ret == -1){LOG_ERROR("rpc服务器启动失败");abort();}}FileServer::ptr build(){if(!_registry){LOG_ERROR("服务注册客户端对象未构造");abort();}if(!_server){LOG_ERROR("rpc服务器对象未构造");abort();}FileServer::ptr FileServer(new lkm_im::FileServer(_registry,_server));return FileServer;}private:Registry::ptr _registry;    //服务注册对象std::shared_ptr<brpc::Server> _server;  //rpc服务器};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1539705.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

两台虚拟机之分布式部署

Apache2 和 PHP 安装 在虚拟机1上执行以下步骤: 更新系统包列表: sudo apt update安装 Apache2: sudo apt install apache2 -y安装 PHP 及其扩展: sudo apt install php libapache2-mod-php php-mysql配置Apache和PHP sudo nano /etc/apache2/mods-enabled/dir.conf#…

Netty笔记10-Netty参数调优

文章目录 一、CONNECT_TIMEOUT_MILLISCONNECT_TIMEOUT_MILLIS设置为1秒超时CONNECT_TIMEOUT_MILLIS设置为5秒超时注意事项 二、SO_BACKLOG代码示例注意事项 三、ulimit -n(文件描述符)设置文件描述符限制在注意事项 四、TCP_NODELAY使用 TCP_NODELAY 的场景注意事项 五、SO_SND…

【Git原理与使用】版本管理与分支管理(1)

目录 一、基本操作 1、初识Git 2、Git安装[Linux-centos] 3、Git安装[ Linnx-ubuntu] 4、创建git本地仓库 5、配置Git 6、认识工作区、暂存区、版本库 7、添加文件 8、查看历史提交记录 9、查看.git文件目录结构 10、查看版本库对象的内容 11、小结&#xff08;在本地的.git仓库…

VS code EXPLORER 中不显示指定文件及文件夹设置(如.pyc, __pycache__, .vscode 文件)

VS code EXPLORER 中不显示指定文件及文件夹设置 引言正文方法1打开方式1打开方式2 方法2 引言 VS code 号称地表最强轻量级编译器&#xff0c;其最大的优势在于用户可以根据自己的需求下载适合自己的 extension。从而定制个性化的编译器。然而&#xff0c;本人今天遇到了一个…

鹰眼降尘监测

鹰眼系统检测原理根据应用领域的不同而有所差异。以下是朗观视觉小编整理的几个主要应用领域及其检测原理的概述&#xff1a; 1. 体检领域 在体检领域&#xff0c;鹰眼通常指的是一种全身扫描仪器&#xff0c;如法国鹰眼检测全身扫描系统。该系统根据生理反馈信号的单向导通&a…

基于ssm的快餐店点餐系统设计与实现

需要项目源码请联系我&#xff0c;目前有各类成品 毕设 javaweb ssh ssm springboot等等项目框架&#xff0c;源码丰富。 专业团队&#xff0c;咨询就送开题报告&#xff0c;活动限时免费&#xff0c;有需要的朋友可以来留言咨询。 一、摘要 进入二十一世纪以来&#xff0c;计…

深度学习自编码器 - 收缩自编码器(CAE)篇

序言 在深度学习的浪潮中&#xff0c;收缩自编码器&#xff08; Compressive Autoencoder, CAE \text{Compressive Autoencoder, CAE} Compressive Autoencoder, CAE&#xff09;作为自编码器的一种高级形式&#xff0c;正逐步崭露头角。收缩自编码器在保留自编码器核心功能—…

QT For Android开发-打开PPT文件

一、前言 需求&#xff1a; Qt开发Android程序过程中&#xff0c;点击按钮就打开一个PPT文件。 Qt在Windows上要打开PPT文件或者其他文件很容易。可以使用QDesktopServices打开文件&#xff0c;非常方便。QDesktopServices提供了静态接口调用系统级别的功能。 这里用的QDesk…

高效开发,从暗藏玄机的文件系统开始

4G-Cat.1模组的文件系统关乎数据传输速度、存储效率&#xff0c;以及数据安全性等等诸多因素&#xff0c;在应用开发中极为重要。 本期&#xff0c;我们来学习合宙Air201的实用示例——文件系统的使用 Air201文件系统的使用 合宙Air201资产定位模组——是一个集成超低功耗4G通…

深入探索迭代器模式的原理与应用

&#x1f3af; 设计模式专栏&#xff0c;持续更新中 欢迎订阅&#xff1a;JAVA实现设计模式 &#x1f6e0;️ 希望小伙伴们一键三连&#xff0c;有问题私信都会回复&#xff0c;或者在评论区直接发言 迭代器模式 &#x1f4bb; 迭代器模式 (Iterator Pattern) 是一种行为设计模…

saltstack高级用法

一、saltstack的高级用法 一、job管理 1、job简介 Jid&#xff1a;job id&#xff0c;格式为%Y%m%d%H%M%S%fmaster在下发指令消息时&#xff0c;会附带上产生的Jid&#xff0c;minion在接收到指令开始执行时&#xff0c;会在本地的cachedir&#xff08;默认是/var/cache/salt/…

力扣 2824.统计和小于目标的下标对数目

文章目录 题目介绍解法 题目介绍 解法 题目相当于从数组中选两个数&#xff0c;我们只关心这两个数的和是否小于 target&#xff0c;由于 abba&#xff0c;无论如何排列数组元素&#xff0c;都不会影响加法的结果&#xff0c;所以排序不影响结果的数量。 排序后&#xff1a; …

CDH Hive集群的create/drop慢问题,在200s 多一点处理分析

现象&#xff1a; CREATE TABLE test911 (SN String,PN_CODE String); Total time spent in this metastore function was greater than 1000ms : createTable_(Table, )200091 Hive集群的 create/drop 操作时间基本都稳定在 200s 多一点。 分析&#xff1a; HMS会实时向Sentr…

实战OpenCV之图像阈值处理

基础入门 图像阈值处理是一种二值化技术&#xff0c;它基于预设的阈值&#xff0c;可以将图像中的像素分为两大类&#xff1a;一大类是背景&#xff0c;另一大类是前景或目标对象。这个过程涉及将图像中的每个像素值与阈值进行比较&#xff0c;并根据比较结果决定保留原始值还是…

jmeter得到的文档数据处理

通过前面jmeter得到的输出文档&#xff0c;这里是txt文档&#xff0c;里面包含了很多条数据&#xff0c;每条数据的结构如下&#xff1a; 【request】 uuid&#xff1a;xxxxxxx timestamp&#xff1a;xxxxxxxx No.x question&#xff1a;xxxxxxx 【response】 code&#…

防火墙配置变更管理

在任何组织中&#xff0c;当涉及到网络安全时&#xff0c;频繁地更换防火墙是必要的&#xff0c;实施简化的防火墙更改管理策略模板可以减少管理时间&#xff0c;还可以减少每次变更引入新的安全性或合规性问题的可能性。典型的防火墙变更管理流程将包括以下步骤&#xff1a; …

排序----插入排序

一开始把第一个元素看成是有序的&#xff0c;然后从第二个元素开始拿出来与前面的数据比较&#xff0c;若前面的数据小&#xff0c;就把前面的数据不断后移&#xff08;注意要把拿出来的那个元素提前保存下来&#xff09;&#xff0c;直到遇到比自己小的元素&#xff0c;然后插…

大语言模型-教育方向数据集

大语言模型-教育方向数据集 编号论文数据集1Bitew S K, Hadifar A, Sterckx L, et al. Learning to Reuse Distractors to Support Multiple-Choice Question Generation in Education[J]. IEEE Transactions on Learning Technologies, 2022, 17: 375-390.Televic, NL, https…

Java 每日一刊(第12期):面向对象

“任何复杂的程序&#xff0c;都可以通过分解成若干个简单的问题来解决。” 前言 这里是分享 Java 相关内容的专刊&#xff0c;每日一更。 本期将为大家带来以下内容&#xff1a; 类对象类与对象的关系Java 中的三种变量类型OOP 的三大特性 类 类 是对现实世界中某类事物…

AntFlow系列教程之流程拒绝

这是开源项目AntFlow的一个系统入门使用教程.AntFlow是一款开源免费的企业级低代码工作流引擎.仿照钉钉设计,极大降低流程设计、开发和维护成本。详细介绍请查看历史文章&#xff1a;AntFlow开源仿钉钉低代码工作流平台集成RuoYi版本来啦 流程拒绝和流程同意提交的参数是一样的…