项目实现:云备份(一)
云备份
- 功能介绍
- 服务端实现的功能
- 服务端模块划分
- 客户端实现的功能
- 客户端模块划分
- 环境搭建
- 更新 gcc 版本至 7.3
- 安装 json 库
- 下载 bundle 数据压缩库 与 httplib 网络库
- 知识铺垫
- bundle 数据压缩库介绍
- 实现文件的压缩功能
- 实现文件解压缩功能
- httplib 网络库介绍
- 搭建简单的服务器
- 搭建简单的客户端
功能介绍
服务端实现的功能
- 支持客户端的文件上传功能
- 支持客户端文件备份列表查看功能(网页形式查看)
- 支持客户端文件下载功能(断点续传)
- 热点文件功能管理(对长时间没有访问的文件进行压缩存储)
服务端模块划分
- 数据管理模块:将客户端上传的文件进行数据管理(包括文件的大小、文件类型、压缩包名称…)方便随时的获取
- 网络通信模块:实现与客户端之间的网络通信
- 业务处理模块:文件上传、文件下载(断点续传)、网页文件列表展示
- 热点管理模块: 对长时间没有访问的文件进行压缩处理
客户端实现的功能
- 指定文件夹中的文件检测(获取文件夹中都有什么文件)
- 判断指定文件是否需要备份(防止文件重复备份),备份新文件、已备份却被修改后的文件
- 将需要备份的文件上传备份到服务器上
客户端模块划分
- 数据管理模块:备份文件的的信息
- 文件检测模块:监控指定的文件夹,是否存在需要备份的文件
- 网络通信模块:搭建网络通信客户端,将需要备份的文件数据上传到服务端
环境搭建
更新 gcc 版本至 7.3
- 更新新的 apt 源:
sudo apt update
- 安装 7.3 版本的 gcc:
sudo apt install gcc-7 g++-7
- 配置对应的文件
echo "source /opt/rt/devtoolset-7/enable" >> ~./bashrc
安装 json 库
json 库的使用具体可以参考小编的这篇文章:json 库的使用
下载 bundle 数据压缩库 与 httplib 网络库
- 安装 bundle 库,这里参考了github 上的资源
https://github.com/r-lyeh-archived/bundle.git
sudo yum install git #安装git
git clone https://github.com/r-lyeh-archived/bundle.git #指定路径
- 下载网络库,这里参考了github 上的资源 :
https://github.com/yhirose/cpp-httplib.git
git clone https://github.com/yhirose/cpp-httplib.git #指定路径
知识铺垫
bundle 数据压缩库介绍
BundleBundle 是一个嵌入式压缩库,支持23种压缩算法和2种存档格式。使用时加入 bundle.h
和 bundle.cpp
文件即可!
实现文件的压缩功能
下面是用 bundle 库进行压缩文件的一段示例代码:
#include <iostream>
#include <string>
#include <fstream>
#include "bundle.h"
int main(int argc, char* argv[])
{
if (argc < 3)
{
std::cout <<"argv[1] 是原始文件路径名称\n";
std::cout <<"argv[2] 是压缩包名称\n";
return -1;
}
std::string ifilename = arg[1]; //要压缩的文件
std::string ofilename = arg[2]; //压缩的成文件
std::ifstream ifs;
ifs.open(ifilename, std::ios::binary); //以二进制的方式打开原始文件
ifs.seekg(0, std::ios::end); //直接跳转到读写的末尾位置
size_t fsize = ifs.tellg(); //获取原生文件的长度
ifs.seekg(0, std::ios::beg); //跳转到文件的开始
std::string body;
body.resize(fsize);//调整body大小为原始文件大小
ifs.read(&body[0], fsize);//读取原始文件的所有数据到body中
std::string packed = bundle::pack(bundle::LZIP, body); //将body的数据压缩到packed中
std::ofstream ofs;
ofs.open(ofilename, std::ios::binary);//以二进制的方式打开压缩文件
ofs.write(&packed, packed.size()); //将刚刚压缩的数据写入到压缩文件中
//关闭文件
ifs.close();
ofs.close();
return 0;
}
在使用 g++ 进行编译时,需要带上 -lpthread
选项。因为 bundle.cpp 文件中使用了原生线程库,防止编译报错。
实现文件解压缩功能
下面是用 bundle 库进行解压文件的一段示例代码:
#include <iostream>
#include <string>
#include <fstream>
#include "bundle.h"
int main(int argc, char *argv[])
{
if (argc < 3) {
printf("argv[1]是压缩包名称\n");
printf("argv[2]是解压后的文件名称\n");
return -1;
}
std::string ifilename = argv[1];//压缩包名
std::string ofilename = argv[2];//解压缩后文件名
std::ifstream ifs;
ifs.open(ifilename, std::ios::binary);
ifs.seekg(0, std::ios::end);
size_t fsize = ifs.tellg();
ifs.seekg(0, std::ios::beg);
std::string body;
body.resize(fsize);
ifs.read(&body[0], fsize);
ifs.close();
std::string unpacked = bundle::unpack(body);//对压缩包数据解压缩
std::ofstream ofs;
ofs.open(ofilename, std::ios::binary);
ofs.write(&unpacked[0], unpacked.size());
ofs.close();
return 0;
}
压缩和解压过程大致相似,读取对应的文件数据进行 压缩/解压,再调用 bundle 库的函数即可.
比较两个文件的内容是否相同可以使用:md5sum
命令
md5sum test.cpp
md5sum
命令是通过文件内容进行大量的哈希运算形成一个独属于这个文件的标识数字,如果两个文件内容有所差异的话,生成的 md5 值是不相等的。
httplib 网络库介绍
httplib 是一个以 C++11 单文件头的跨平台 HTTP/HTTPS 库。
httplib 网络库常用于搭建一个简单的 http 服务器或者客户端的库,可以让我们免去搭建服务器或客户端的时间,提高开发效率。在使用时加入 httplib.h
头文件即可!
搭建简单的服务器
#include "httplib.h"
void Hello(const httplib::Request &req, httplib::Response &rsp)
{
rsp.set_content("welcome to my server", "text/plain"); //设置get响应的资源为文本
rsp.status = 200;
}
void Numbers(const httplib::Request &req, httplib::Response &rsp)
{
auto num = req.matches[1]; //matches数组中,除了0下标为整体的path,往后的下标保存的是依次捕捉的数据
rsp.set_content(num, "text/plain");
rsp.status = 200;
}
void Multipart(const httplib::Request &req, httplib::Response &rsp)
{
auto ret = req.has_file("file");
if(ret == false) //不是文件
{
std::cout << "no file upload\n";
rsp.status = 400;
return;
}
const auto& file = req.get_file_value("file"); //上传文件内容
rsp.body.clear(); //清空body内容
//设置响应
rsp.body = file.filename; //文件名称
rsp.body += "/n";
rsp.body += file.content;//响应文件内容
rsp.set_header("Content-Type", "text/plain");
rsp.status = 200;
}
int main()
{
httplib::Server server; //实例化Server类用于搭建服务器
//分别处理不同的请求
server.Get("/hi", Hello);
server.Get(R"(/hi/(\d+))", Numbers); //R"()"是防止反斜杠/的转译
server.Post("/multipart", Multipart);
server.listen("0.0.0.0", 8080); //监听来自客户端的连接,任意网卡都可以接收来访,服务器端口8080
return 0;
}
搭建简单的客户端
#include "httplib.h"
#define SERVER_IP "xx.xx.xx.xx"
#define SERVER_PORT 8080
int main()
{
//实例化client对象,用于搭建客户端
httplib::Client client(SERVER_IP, SERVER_PORT); //IP+端口号
//设置上传数据的信息
httplib::MultipartFormData item;
item.name = "file"; //上传的数据为文件
item.filename = "hello.txt"; //文件名
item.content = "hello world"; //文件内容
item.content_type = "text/plain"; //文件类型
httplib::MultipartFormDataItems items; //是一个以 MultipartFormData 类型的数组
items.push_back(item);
auto res = client.Post("/multipart", items); //将数据上传到服务端
//输出服务器返回传输的内容
std::cout << res->status << std::endl;
std::cout << res->body << std::endl;
return 0;
}
项目的基本功能介绍就到这里,后续会持续更新相应的内容。