东莞中堂网站建设,手机网站返回跳转页面,仿站吧,如何迅速k掉网站文章目录 专栏导读1.客户端数据管理模块实现2.客户端文件检测模块实现3.客户端文件备份模块设计4.客户端文件备份模块实现 专栏导读 #x1f338;作者简介#xff1a;花想云 #xff0c;在读本科生一枚#xff0c;C/C领域新星创作者#xff0c;新星计划导师#xff0c;阿… 文章目录 专栏导读1.客户端数据管理模块实现2.客户端文件检测模块实现3.客户端文件备份模块设计4.客户端文件备份模块实现 专栏导读 作者简介花想云 在读本科生一枚C/C领域新星创作者新星计划导师阿里云专家博主CSDN内容合伙人…致力于 C/C、Linux 学习。 专栏简介本文收录于 C项目——云备份 相关专栏推荐C语言初阶系列、C语言进阶系列 、C系列、数据结构与算法、Linux 项目Gitee链接https://gitee.com/li-yuanjiu/cloud-backup 1.客户端数据管理模块实现
客户端要实现的功能是对指定文件夹中的文件自动进行备份上传。但是并不是所有的文件每次都需要上传我们需要能够判断哪些文件需要上传哪些不需要因此需要将备份的文件信息给管理起来作为下一次文件是否需要备份的判断。因此需要被管理的信息包含以下
文件路径名称文件唯一标识由文件名最后一次修改时间文件大小组成的一串信息
客户端数据管理模块可直接由服务端数据管理模块改造得到因为其只需要服务端数据管理模块代码中一小部分功能。
#ifndef __MY_DATA__
#define __MY_DATA__
#include unordered_map
#include sstream
#include util.hppnamespace cloud
{class DataManager{public:DataManager(const std::string backup_file) :_backup_file(backup_file){InitLoad();}bool Storage(){// 1.获取所有的备份信息std::stringstream ss;auto it _table.begin();for (; it ! _table.end(); it){// 2.将所有信息进行指定持久化格式的组织ss it-first it-second \n;}// 3.持久化存储FileUtil fu(_backup_file);fu.SetContent(ss.str());return true;}bool InitLoad(){// 1.从文件中读所有数据FileUtil fu(_backup_file);std::string body;fu.GetContent(body);// 2.进行数据解析添加到表当中std::vectorstd::string array;Split(body, \n, array);for (auto a : array){std::vectorstd::string tmp;Split(a, , tmp);if (tmp.size() ! 2){continue;}_table[tmp[0]] tmp[1];}return true;}bool Insert(const std::string key, const std::string val){_table[key] val;Storage();return true;}bool Updata(const std::string key, const std::string val){_table[key] val;Storage();return true;}bool GetOneByKey(const std::string key, std::string* val){auto it _table.find(key);if (it _table.end()){return false;}*val it-second;return true;}private:int Split(const std::string str, const std::string sep, std::vectorstd::string* array){int count 0;size_t pos 0, idx 0;while (1){pos str.find(sep, idx);if (pos std::string::npos){break;}if (pos idx){idx pos sep.size();continue;}std::string tmp str.substr(idx, pos - idx);array-push_back(tmp);count;idx pos sep.size();}if (idx str.size()){array-push_back(str.substr(idx));count;}return count;}private:std::string _backup_file; // 备份信息持久化存储文件std::unordered_mapstd::string, std::string _table;};
}
#endif2.客户端文件检测模块实现
同样的客户端文件实用工具类其实与服务端的文件实用工具类雷同只是功能需求并没有服务端那么多复制过来即可。
#ifndef __MY_UTIL__
#define __MY_UTIL__
/*1.获取文件大小2.获取文件最后一次修改时间3.获取文件最后一次访问时间4.获取文件路径名中的文件名称 /abc/test.txt - test.txt5.向文件写入数据6.获取文件数据7.获取文件指定位置 指定数据长度8.判断文件是否存在9.创建目录10.浏览获取目录下的所有文件路径名11.压缩文件12.解压缩所有文件
*/
#include iostream
#include fstream
#include string
#include vector
#include experimental/filesystem
#include sys/stat.hnamespace cloud
{namespace fs std::experimental::filesystem;class FileUtil{public:FileUtil(const std::string filename) :_filename(filename){}int64_t FileSize(){struct stat st;if(stat(_filename.c_str(), st) 0){std::cout get file size failed! std::endl;return 0;}return st.st_size;}time_t LastMTime(){struct stat st;if(stat(_filename.c_str(), st) 0){std::cout get last modify time failed! std::endl;return -1;}return st.st_mtime;}time_t LastATime(){struct stat st;if(stat(_filename.c_str(), st) 0){std::cout get last access time failed! std::endl;return -1;}return st.st_atime; }std::string FileName(){size_t pos _filename.find_last_of(/);if(pos std::string::npos){return _filename;}return _filename.substr(pos1);}bool GetPosLen(std::string *body, size_t pos, size_t len){size_t fsize FileSize();if(pos len fsize){std::cout get file len error std::endl;return false;}std::ifstream ifs;ifs.open(_filename, std::ios::binary);if(ifs.is_open() false){std::cout open file failed! std::endl;return false;}ifs.seekg(pos, std::ios::beg);body-resize(len);ifs.read((*body)[0], len);if(ifs.good() false){std::cout get file content failed std::endl;ifs.close();return false;}ifs.close();return true;}bool GetContent(std::string *body){size_t fsize FileSize();return GetPosLen(body, 0, fsize);}bool SetContent(const std::string body){std::ofstream ofs;ofs.open(_filename, std::ios::binary);if(ofs.is_open() false){std::cout write open file failed std::endl;return false;}ofs.write(body[0], body.size());if(ofs.good() false){std::cout write open file failed std::endl;ofs.close();return false;}ofs.close();return true;}bool Exists(){return fs::exists(_filename);}bool Remove(){if(Exists() false){return true;}remove(_filename.c_str());return true;}bool CreateDirectory(){if(Exists()) return true;return fs::create_directories(_filename);}bool ScanDirectory(std::vectorstd::string *array){CreateDirectory();for(auto p : fs::directory_iterator(_filename)){if(fs::is_directory(p) true) continue;// relative_path 带有路径的文件名array-push_back(fs::path(p).relative_path().string());}return true;}private:std::string _filename;};
}
#endif3.客户端文件备份模块设计
回顾客户端自动将指定文件夹中的文件备份到服务器流程
遍历指定文件夹逐一判断文件是否需要备份需要备份的文件进行上传备份
客户端文件备份类主要包含以下成员
#define SERVER_ADDR 47.108.25.253 // 服务器IP
#define SERVER_PORT 8989 // 服务器端口
class Backup
{
public:Backup(const std::string back_dir, const std::string back_file);// 生成文件的唯一标识std::string GetFileIdentifier(std::string filename);// 上传文件函数bool Upload(const std::string filename); // 判断是否需要上传bool IsNeedUpload(const std::string filename);// 主逻辑执行函数bool RunMoudle();
private:std::string _back_dir; // 监控的文件目录DataManager* _data;
};4.客户端文件备份模块实现
#ifndef __MY_CLOUD__
#define __MY_CLOUD__
#include data.hpp
#include httplib.h
#include Windows.h
#define SERVER_ADDR 47.108.25.253
#define SERVER_PORT 8989
namespace cloud
{class Backup{public:Backup(const std::string back_dir, const std::string back_file):_back_dir(back_dir){_data new DataManager(back_file);}std::string GetFileIdentifier(std::string filename){FileUtil fu(filename);std::stringstream ss;ss fu.FileName() - fu.FileSize() - fu.LastMTime();return ss.str();}bool Upload(const std::string filename){// 1.获取文件数据FileUtil fu(filename);std::string body;fu.GetContent(body);// 2.搭建http客户端上传文件数据httplib::Client client(SERVER_ADDR, SERVER_PORT);httplib::MultipartFormData item;item.content body;item.filename fu.FileName();item.content_type application/octet-stream;httplib::MultipartFormDataItems items;items.push_back(item);auto res client.Post(/upload, items);if (!res || res-status ! 200){return false;}return true;}bool IsNeedUpload(const std::string filename){// 需要上传的文件判断条件文件是新增的不是新增的但是被修改过// 文件是新增的看一下有没有备份信息// 不是新增的但是被修改过有历史信息但是历史信息的唯一标识符与当前最新的唯一标识符不一致std::string id;if (_data-GetOneByKey(filename, id) ! false){// 有历史信息std::string new_id GetFileIdentifier(filename);if (new_id ! id){return false;}}//判断一个文件是否有一段时间没有被修改过了FileUtil fu(filename);if (time(NULL) - fu.LastMTime() 3){return false;}return true;}bool RunMoudle(){while (1){// 1.遍历获取指定文件夹中所有文件FileUtil fu(_back_dir);std::vectorstd::string array;fu.ScanDirectory(array);// 2.逐个判断是否需要上传for (auto a : array){if (IsNeedUpload(a) false)continue;// 3.如果需要则上传文件if (Upload(a) true){_data-Insert(a, GetFileIdentifier(a));}}Sleep(1);}}private:std::string _back_dir;DataManager* _data;};
}
#endif