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

news2025/4/17 23:22:02

在这里插入图片描述

云备份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;
			}
	};

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

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

相关文章

考研分享第2期 | 中央财经大学管理科学跨考北大软微金融科技406分经验分享

一、个人信息 本科院校&#xff1a;中央财经大学 管理科学与工程学院 管理科学专业 上岸院校&#xff1a;北京大学 软件与微电子学院 金融科技专业硕士 考试科目&#xff1a; 初试&#xff1a;思想政治理论 英语一 数学二 经济学综合 面试考察范围广&#xff0c;包括英语自…

代码随想录算法训练营第四十九天丨 动态规划part12

309.最佳买卖股票时机含冷冻期 思路 相对于动态规划&#xff1a;122.买卖股票的最佳时机II (opens new window)&#xff0c;本题加上了一个冷冻期 在动态规划&#xff1a;122.买卖股票的最佳时机II (opens new window)中有两个状态&#xff0c;持有股票后的最多现金&#xf…

头歌答案--爬虫实战

目录 urllib 爬虫 第1关&#xff1a;urllib基础 任务描述 第2关&#xff1a;urllib进阶 任务描述 requests 爬虫 第1关&#xff1a;requests 基础 任务描述 第2关&#xff1a;requests 进阶 任务描述 网页数据解析 第1关&#xff1a;XPath解析网页 任务描述 第…

算法导论6:摊还分析,显式与隐式

P258 摊还分析概念 聚合分析&#xff0c;利用它&#xff0c;我们证明对于n&#xff0c;一个n个操作的序列最坏情况下的花费的总时间为T(n)&#xff0c;因此&#xff0c;在最坏情况下&#xff0c;每个操作的平均代价&#xff08;摊还代价&#xff09;为T(n)/n 举了例子来形容这…

asp.net 在线音乐网站系统VS开发sqlserver数据库web结构c#编程Microsoft Visual Studio

一、源码特点 asp.net 在线音乐网站系统是一套完善的web设计管理系统&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为vs2010&#xff0c;数据库为sqlserver2008&#xff0c;使用c#语言 开发 asp.net 在线音乐网站系统1 应用…

pyorch Hub 系列#4:PGAN — GAN 模型

一、主题描述 2014 年生成对抗网络的诞生及其对任意数据分布进行有效建模的能力席卷了计算机视觉界。两人范例的简单性和推理时令人惊讶的快速样本生成是使 GAN 成为现实世界中实际应用的理想选择的两个主要因素。 然而&#xff0c;在它们出现后的很长一段时间内&#xff0c;GA…

Clickhouse学习笔记(8)—— 建表优化

数据类型 时间字段 建表时能用数值型或日期时间类型&#xff08;DateTime&#xff09;表示的字段就不要用字符串 因为clickhouse进行分区时一般使用时间字段来进行分区&#xff0c;而将时间字段使用DateTime表示&#xff0c;不需要经过函数转换处理&#xff0c;执行效率高、…

开放领域问答机器人2——开发流程和方案

开放领域问答机器人是指在任何领域都能够回答用户提问的智能机器人。与特定领域问答机器人不同&#xff0c;开放领域问答机器人需要具备更广泛的知识和更灵活的语义理解能力&#xff0c;以便能够回答各种不同类型的问题。 开发开放领域问答机器人的流程和方案可以包括以下步骤…

【视觉SLAM十四讲学习笔记】第二讲——初识SLAM

专栏系列文章如下&#xff1a; 【视觉SLAM十四讲学习笔记】第一讲 一个机器人&#xff0c;如果想要探索某一块区域&#xff0c;它至少需要知道两件事&#xff1a; 我在什么地方——定位周围环境是什么样——建图 一方面需要明白自身的状态&#xff08;即位置&#xff09;&#…

最详细ChatGPT+AI绘画+企业知识库+视频去水印系统源码搭建流程,手把手教你搭建

一、系统介绍 这款源码搭载了强大的AI问答功能&#xff0c;是基于目前最强大AI大语言模型ChatGPT进行开发的Ai智能问答系统&#xff0c;并使用stablediffusion加最新的comfyui作为底层技术的绘画系统,使用comfyui的api接口&#xff0c;可以更灵活的定制自己的绘画工作流&#…

2.2 CE修改器:未知数值扫描

本关需要扫描未知数只扫描&#xff0c;要在不知道初始值的情况下找到一个在0到500之间的数值。首先&#xff0c;选择“未知的初始值”扫描方式&#xff0c;在数值类型中选择 4 字节&#xff0c;并点击“首次扫描”以开始扫描。扫描结束后&#xff0c;点击“打我”按钮进行一些操…

Java基础(第六期):Java基础巩固、逢七跳过、数组求和、判断数组是否相等、数组逆置、元素位置查找、评委打分、随机产生验证码

Java基础专栏【点击跳转学习】 Java基础&#xff08;第六期&#xff09;&#xff1a;对前五期的综合练习 文章目录 综合练习巩固JAVA基础第六期一、逢 7 跳过二、数组元素求和三、判断两个数组元素是否相同四、查找元素在数组中的索引五、数组元素反转使用for循环的实现方式一、…

【LeetCode刷题-二分查找】--278.第一个错误的版本

278.第一个错误的版本 /* The isBadVersion API is defined in the parent class VersionControl.boolean isBadVersion(int version); */public class Solution extends VersionControl {public int firstBadVersion(int n) {int left 1,right n;while(left < right){int…

webpack工作原理

目录 合并代码模块化webpack 的打包webpack 的结构webpack 的源码addEntry 和 _addModuleChainbuildModuleCompilation 的钩子产出构建结果 了解 webpack 实现原理&#xff0c;掌握 webpack 基础的工作流程&#xff0c;在平时使用 webpack 遇见问题时&#xff0c;能够帮助我们洞…

Doris学习--1、Doris简介、操作Doris、Doris架构(数据模型)

星光下的赶路人star的个人主页 心之所向&#xff0c;剑之所往 文章目录 1、Doris简介1.1 快速开始1.2 安装配置1.2.1 应知前提1.2.2 配置Doris1.2.2.0 配置前提1.2.2.1 配置FE&#xff08;Frontend&#xff09;1.2.2.2 启动FE1.2.2.3 连接FE1.2.2.4 停止FE1.2.2.5 配置BE&#…

【函数讲解】pygmo中的函数 fast_non_dominated_sorting() + 利用支配关系,学习一个SVM分类器,将解分为两类

这个函数是用来执行非支配排序的&#xff0c;可以分层构建Pareto&#xff0c;并返回每一层的解以及每个解支配其他解的索引、解被其他解支配的次数、解所在的非支配层级。这个函数对这些解进行非支配排序&#xff0c;并返回四个数组&#xff1a;ndf, dl, dc, 和 ndr。 ndf (Non…

2.3 CE修改器:浮点数扫描

本关需要使用 Cheat Engine 工具对浮点数进行扫描&#xff0c;完成修改任务。浮点数是一种带有小数点的数值&#xff0c;通过“浮点数”扫描方式进行修改。本关中&#xff0c;健康值为单精度浮点数&#xff0c;弹药值为双精度浮点数&#xff0c;需要将这两项数值都修改为 5000 …

InSAR形变监测方法与研究进展(朱建军,中南大学)

文章目录 摘要引言InSARInSAR原理SAR卫星 InSAR监测技术D-InSARMT-InSARPS-InSARSBAS-InSARDS-InSAR&#xff08;Distributed Scatterer InSAR&#xff09;MAI&#xff08;Multi-Aperture InSAR, 多孔径InSAR&#xff09; InSAR形变监测应用与发展城市沉降监测矿山形变监测地震…

深度探究深度学习常见数据类型INT8 FP32 FP16的区别即优缺点

定点和浮点都是数值的表示&#xff08;representation&#xff09;&#xff0c;它们区别在于&#xff0c;将整数&#xff08;integer&#xff09;部分和小数&#xff08;fractional&#xff09;部分分开的点&#xff0c;点在哪里。定点保留特定位数整数和小数&#xff0c;而浮点…