【云备份|| 日志 day6】文件业务处理模块

在这里插入图片描述

云备份day6

  • 业务处理

业务处理

云备份项目中 ,业务处理模块是针对客户端的业务请求进行处理,并最终给与响应。而整个过程中包含以下要实现的功能:

  1. 借助网络通信模块httplib库搭建http服务器与客户端进行网络通信
  2. 针对收到的请求进行对应的业务处理并进行响应(文件上传,列表查看,文件下载(包含断点续传))

业务处理模块要对客户端的请求进行处理,那么我们就需要提前定义好客户端与服务端的通信,明确客户端发送什么样的请求,服务端处理后应该给与什么样的响应,而这就是网络通信接口的设计。

HTTP文件上传:

request请求

POST /upload HTTP/1.1
Content-Length:11
Content-Type:multipart/form-data;boundary= ----WebKitFormBoundary+16字节随机字符
------WebKitFormBoundary
Content-Disposition:form-data;filename="a.txt";
hello world
------WebKitFormBoundary--

respons响应

HTTP/1.1 200 OK
Content-Length: 0

HTTP文件列表获取:

request请求

GET /list HTTP/1.1
Content-Length: 0

响应

HTTP/1.1 200 OK
Content-Length:
Content-Type: text/html

<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Page of Download</title>
</head><body>
<h1>Download</h1>
<table><tr>
<td><a href="/download/a.txt"> a.txt </a></td>
<td align="right"> 1994-07-08 03:00 </td>
<td align="right"> 27K </td>
</tr></table></body>

HTTP文件下载:

请求

GET /download/a.txt http/1.1
Content-Length: 0

响应

HTTP/1.1 200 OK
Content-Length: 100000
ETags: "filename-size-mtime一个能够唯一标识文件的数据"
Accept-Ranges: bytes

服务端业务处理模块实现-业务处理类设计

extern cloud::DataManager *_data;
class Service{
private:
int _server_port;
std::string _server_ip;
std::string _url_prefix;
httplib::Server _srv;
public:
static void Upload(const httplib::Request &req, httplib::Response &rsp);
static void List(const httplib::Request &req, httplib::Response &rsp);
static void Download(const httplib::Request &req,httplib::Response &rsp);
public:
Service();
bool RunModule();
}

代码:

class Service{
		private:
			int _server_port;
			std::string _server_ip;
			std::string _download_prefix;
			httplib::Server _server;
		private:
			static void Upload(const httplib::Request &req, httplib::Response &rsp) {
				// post /upload  文件数据在正文中(正文并不全是文件数据)
				auto ret = req.has_file("file");//判断有没有上传的文件区域
				if (ret == false){
					rsp.status = 400;
					return;
				}
				const auto& file = req.get_file_value("file");
				//file.filename//文件名称    file.content//文件数据
				std::string back_dir = Config::GetInstance()->GetBackDir();
				std::string realpath = back_dir + FileUtil(file.filename).FileName();
				FileUtil fu(realpath);
				fu.SetContent(file.content);//将数据写入文件中;
				BackupInfo info;
				info.NewBackupInfo(realpath);//组织备份的文件信息
				_data->Insert(info);//向数据管理模块添加备份的文件信息
				return ;
			}
			static std::string TimetoStr(time_t t) {
				std::string tmp = std::ctime(&t);
				return tmp;
			}
			static void ListShow(const httplib::Request &req, httplib::Response &rsp){
				//1. 获取所有的文件备份信息
				std::vector<BackupInfo> arry;
				_data->GetAll(&arry);
				//2. 根据所有备份信息,组织html文件数据
				std::stringstream ss;
				ss << "<html><head><title>Download</title></head>";
				ss << "<body><h1>Download</h1><table>";
				for (auto &a : arry){
					ss << "<tr>";
					std::string filename = FileUtil(a.real_path).FileName();
					ss << "<td><a href='" << a.url << "'>" << filename << "</a></td>";
					ss << "<td align='right'>" << TimetoStr(a.mtime) << "</td>";
					ss << "<td align='right'>" << a.fsize / 1024 << "k</td>";
					ss << "</tr>";
				}
				ss << "</table></body></html>";
				rsp.body = ss.str();
				rsp.set_header("Content-Type", "text/html");
				rsp.status = 200;
				return ;
			}
			static std::string GetETag(const BackupInfo &info) {
				// etg :  filename-fsize-mtime
				FileUtil fu(info.real_path);
				std::string etag = fu.FileName();
				etag += "-";
				etag += std::to_string(info.fsize);
				etag += "-";
				etag += std::to_string(info.mtime);
				return etag;
			}
			static void Download(const httplib::Request &req, httplib::Response &rsp){
				//1. 获取客户端请求的资源路径path   req.path
				//2. 根据资源路径,获取文件备份信息
				BackupInfo info;
				_data->GetOneByURL(req.path, &info);
				//3. 判断文件是否被压缩,如果被压缩,要先解压缩, 
				if (info.pack_flag == true){
					FileUtil fu(info.pack_path);
					fu.UnCompress(info.real_path);//将文件解压到备份目录下
					//4. 删除压缩包,修改备份信息(已经没有被压缩)
					fu.Remove();
					info.pack_flag = false;
					_data->Update(info);
				}

				bool retrans = false;
				std::string old_etag;
				if (req.has_header("If-Range")) {
					old_etag = req.get_header_value("If-Range");
					//有If-Range字段且,这个字段的值与请求文件的最新etag一致则符合断点续传
					if (old_etag == GetETag(info)) {
						retrans = true;
					}
				}

				//4. 读取文件数据,放入rsp.body中
				FileUtil fu(info.real_path);
				if (retrans == false){
					fu.GetContent(&rsp.body);
					//5. 设置响应头部字段: ETag, Accept-Ranges: bytes
					rsp.set_header("Accept-Ranges", "bytes");
					rsp.set_header("ETag", GetETag(info));
					rsp.set_header("Content-Type", "application/octet-stream");
					rsp.status = 200;
				}else {
					//httplib内部实现了对于区间请求也就是断点续传请求的处理
					//只需要我们用户将文件所有数据读取到rsp.body中,它内部会自动根据请求
					//区间,从body中取出指定区间数据进行响应
					// std::string  range = req.get_header_val("Range"); bytes=start-end
					fu.GetContent(&rsp.body);
					rsp.set_header("Accept-Ranges", "bytes");
					rsp.set_header("ETag", GetETag(info));
					rsp.set_header("Content-Type", "application/octet-stream");
					//rsp.set_header("Content-Range", "bytes start-end/fsize");
					rsp.status = 206;//区间请求响应的是206*****
				}
			}
		public:
			Service(){
				Config *config = Config::GetInstance();
				_server_port = config->GetServerPort();
				_server_ip = config->GetServerIp();
				_download_prefix = config->GetDownloadPrefix();
			}
			bool RunModule() {
				_server.Post("/upload", Upload);
				_server.Get("/listshow", ListShow);
				_server.Get("/", ListShow);
				std::string download_url = _download_prefix + "(.*)";
				_server.Get(download_url, Download);
				_server.listen(_server_ip.c_str(), _server_port);
				return true;
			}
	};

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

算法导论笔记4:散列数 hash

一 了解一些散列的基本概念&#xff0c;仅从文字角度&#xff0c;整理了最基础的定义。 发现一本书&#xff0c;《算法图解》&#xff0c;微信读书APP可读&#xff0c;有图&#xff0c;并且是科普性质的读物&#xff0c;用的比喻很生活化&#xff0c;可以与《算法导论》合并起…

Xshell远程登录 Linux小键盘数字输入变成字母解决办法

Xshell的设置问题&#xff0c;依次查看&#xff1a;文件-->属性-->终端-->VT模式-->初始数字键盘模式更改为&#xff1a;设置普通&#xff08;s&#xff09;

vue-常用指令

​&#x1f308;个人主页&#xff1a;前端青山 &#x1f525;系列专栏&#xff1a;Vue篇 &#x1f516;人终将被年少不可得之物困其一生 依旧青山,本期给大家带来vue篇专栏内容-常用指令 目录 常用指令 1、v-cloak 2、数据绑定指令 3、v-once 4、v-bind&#xff08;重点&a…

在线制作仿真病历证明软件,易语言实现病例报告生成器,取画板快照+标签+编辑框

闲着无聊用易语言开发了一个病例生成器&#xff0c;当然我加了水印的&#xff0c;这个图片你就算截图你也用不了&#xff0c;模板是从百度图库搜的&#xff0c;很多&#xff0c;我就随便找了一个&#xff0c;然后实现逻辑就是加了一个画板&#xff0c;然后载入了素材图&#xf…

2023-11-12 LeetCode每日一题(Range 模块)

2023-03-29每日一题 一、题目编号 715. Range 模块二、题目链接 点击跳转到题目位置 三、题目描述 Range模块是跟踪数字范围的模块。设计一个数据结构来跟踪表示为 半开区间 的范围并查询它们。 半开区间 [left, right) 表示所有 left < x < right 的实数 x 。 实…

采用示波器显示扭矩传感器模拟信号

扭矩传感器输出的信号波形通常是模拟电压信号&#xff0c;可以通过示波器等仪器进行分析。扭矩传感器的输出信号波形通常有两种类型&#xff1a;正弦波和方波。 应变片传感器扭矩测量采用应变电测技术。在弹性轴上粘贴应变计组成测量电桥&#xff0c;当弹性轴受扭矩产生微小变…

【CASS精品教程】cass3d 11.0加载超大影像、三维模型、点云数据

CAD2016+CASS11.0(内置3d)下载与安装: 【CASS精品教程】CAD2016+CASS11.0安装教程(附CASS11.0安装包下载)https://geostorm.blog.csdn.net/article/details/132392530 一、cass11.0 3d支持的数据 cass11.0中的3d模块增加了多种数据的支持,主要有: 1. 三维模型 点击…

Linux学习教程(第二章 Linux系统安装)3

第二章 Linux系统安装 十一、Linux远程管理协议&#xff08;RFB、RDP、Telnet和SSH&#xff09; 提到远程管理&#xff0c;通常指的是远程管理服务器&#xff0c;而非个人计算机。个人计算机可以随时拿来用&#xff0c;服务器通常放置在机房中&#xff0c;用户无法直接接触到…

画面精美传奇手游幽冥传奇【幽冥灭龙传奇】win服务端+双端+GM授权后台+详细教程

搭建资源下载地址&#xff1a;画面精美传奇手游幽冥传奇幽冥灭龙传奇win服务端双端GM授权后台详细教程-海盗空间

Xilinx FPGA平台DDR3设计详解(一):DDR SDRAM系统框架

DDR SDRAM&#xff08;双倍速率同步动态随机存储器&#xff09;是一种内存技术&#xff0c;它可以在时钟信号的上升沿和下降沿都传输数据&#xff0c;从而提高数据传输的速率。DDR SDRAM已经发展了多代&#xff0c;包括DDR、DDR2、DDR3、DDR4和DDR5&#xff0c;每一代都有不同的…

GoF之工厂模式

Spring GoF之工厂模式工厂模式的三种形态简单工厂模式简单工厂模式优缺点 工厂方法模式工厂方法模式的优缺点 GoF之工厂模式 ● 设计模式&#xff1a;一种可以被重复利用的解决方案。 GoF有23种设计模式&#xff0c;还有其它的设计模式&#xff0c;比如&#xff1a;JavaEE的设…

使用 huggingface_hub 镜像下载 大模型

download.py &#x1f447; import os # 配置 hf镜像 os.environ[HF_ENDPOINT] https://hf-mirror.com# 设置保存的路径 local_dir "XXXXXX"# 设置仓库id model_id "sensenova/piccolo-large-zh"cmd f"huggingface-cli download --resume-downlo…

K8S知识点(六)

&#xff08;1&#xff09;资源管理方式1 其他参数 其他参数以json格式显示pod信息 以yaml显示pod信息&#xff1a; 用describe描述容器的详细信息&#xff1a;包括ip啊&#xff0c;镜像啊&#xff0c;端口啊&#xff0c;容器启动经历的历程 创建命名空间Pod&#xff1a; 查询…

[量化投资-学习笔记012]Python+TDengine从零开始搭建量化分析平台-策略回测

上一章节《MACD金死叉策略回测》中&#xff0c;对平安银行这只股票&#xff0c;按照金死叉策略进行了回测。 但通常我们的股票池中有许多股票&#xff0c;每完成一个交易策略都需要对整个股票池进行回测。 下面使用简单的轮询&#xff0c;对整个股票池进行回测。 # 计算单只…

FM模型与POLY2模型

两个核心细节 掌握FM&#xff0c;有两个细节需要注意&#xff1a;参数量级的变化和时间复杂度的变化。 首先对于参数量级&#xff0c;由线性模型到多项式模型到FM模型参数量级变化为&#xff1a; n–>n*n–>kn (k<<n) 其次是由原始FM公式到化简之后的FM公式复杂…

用excel计算一个矩阵的转置矩阵

假设我们的原矩阵是一个3*3的矩阵&#xff1a; 125346789 现在求它的转置矩阵&#xff1a; 鼠标点到一个空白的地方&#xff0c;用来存放结果&#xff1a; 插入-》函数&#xff1a; 选择TRANSPOSE&#xff0c;这个就是求转置矩阵的函数&#xff1a; 点击“继续”&#xff1a…

免费录屏软件哪个好用?免费录屏软件排行榜

对于您的团队&#xff0c;屏幕录像机可以用于多种原因——从为您的网站创建教程到记录反复出现的技术问题&#xff0c;再到向您的营销团队发送快速说明而不是电子邮件。 此外&#xff0c;我们不能忘记产品演示和培训视频&#xff0c;它们可供您团队中的许多部门使用&#xff0…

72 内网安全-域横向CSMSF联动及应急响应初识

目录 演示案例:MSF&CobaltStrike联动ShellWEB攻击应急响应朔源-后门,日志WIN系统攻击应急响应朔源-后门,日志,流量临时给大家看看学的好的怎么干对应CTF比赛 涉及资源 权限维持留到后面在补充&#xff0c;先把后面的知识点给大家讲起来&#xff0c;因为权限维持它是我们前期…

队列Queue

结构特点&#xff1a;先进先出实现模式&#xff1a;单向非循环双指针链表 两个指针分别记录头和尾之所以不用循环链表是添加删除元素都在链表头部进行&#xff0c;不涉及尾部增删操作。 声明队列 声明队列之所以要用到两个结构体是因为除了单个链表节点之外&#xff0c;还需要…

js删除json数据中指定元素

delete 删除数组方法&#xff1a; function removeJSONRows() {var tab {"dataRows": [{"id": 1,"name": "使用部门"},{"id": 2,"name": "车辆走行路线"},{"id": 3,"name": &quo…