云备份客户端——目录遍历模块以及文件备份模块

由于目录遍历我们的实用类工具以及实现,因此我们这里将两个模块合并成一个客户端功能模块

该模块用来实现我们客户端的核心功能:自动将指定文件夹中的文件备份到服务器

而我们这个功能实现的思路也比较简单易懂:

1. 获取目录下所有文件,获取文件信息

2. 对每个文件信息逐一判断是否符合上传条件(新文件,或者修改过的文件)

3. 需要备份的文件用httplib库架设客户端,上传备份带服务器

因此我们接口设计如下:

#pragma once
#include "data_manager.hpp"
#include "util.hpp"

#define SERVER_IP "124.221.185.180"
#define SERVER_PORT "8080"
namespace mjw_cloud
{
	class Client
	{
	public:
		Client(const std::string& obj_dir,const std::string& backup_file)
			:_obj_dir(obj_dir)
		{
			data = new FileDatas(backup_file);
		}
		
		//客户端启动
		bool Run()
		{}
	private:
		//判断文件是否需要上传
		bool UploadJudge(const std::string& filename);
		//获得文件目前唯一标识
		std::string GetFileOnlymark(const std::string& filename);
		//上传文件
		bool Upload(const std::string& filename);
	private:
		std::string _obj_dir;//上传文件目录
		FileDatas* _data;
	};
}

代码实现如下

#pragma once
#include "data_manager.hpp"
#include "util.hpp"
#include "httplib.h"
#include 
#include 

#define SERVER_IP "124.221.185.180"
#define SERVER_PORT 8080
namespace mjw_cloud
{
	class Client
	{
	public:
		Client(const std::string& obj_dir,const std::string& backup_file)
			:_obj_dir(obj_dir)
		{
			_data = new FileDatas(backup_file);
		}
		
		//客户端启动
		bool Run()
		{
			//循环获取目标文件夹下文件信息
			while (1)
			{
				FileUtil fu(_obj_dir);
				std::vector arry;
				fu.ScanDirectory(&arry);
				if (arry.empty())
				{
					//间隔一段时间在继续
					Sleep(1);
					continue;
				}
				for (auto a : arry)
				{
					if (UploadJudge(a))
					{
						Upload(a);
						//上传成功后将文件信息插入到data中
						_data->Insert(a, GetFileOnlymark(a));
						std::cout << a << " upload success" << std::endl;
					}
				}
			}
		}
	private:
		//判断文件是否需要上传
		bool UploadJudge(const std::string& filename)
		{
			//上传条件:1.新增文件 2.修改过的文件
			//判断新增文件
			std::string val;
			if (_data->GetoneByKey(filename, &val) == false)
			{
				return true;
			}
			//非新增文件
			else
			{
				//判断是否修改
				if (val != GetFileOnlymark(filename))
				{
					//被修改文件
					//注意:这里有一种情况
					//一个大文件正在被拷贝到obj_dir中,因此他时刻处于修改状态
					//如果文件修改就备份,那么这个大文件在拷贝过程中可能被备份了几百上千次
					//因此我们对于被修改文件的上传应该再加一个条件
					//修改时间间隔大于3
					FileUtil fu(filename);
					if (time(nullptr) - fu.LastMTime() > 3) return true;
				}
			}
			return false;
		}
		//获得文件目前唯一标识
		std::string GetFileOnlymark(const std::string& filename)
		{
			FileUtil fu(filename);
			std::stringstream ss;
			//文件名-文件大小-文件最后一次修改时间
			ss << filename << "-" << fu.FileSize() << "-" << fu.LastMTime();
			return ss.str();
		}
		//上传文件
		bool Upload(const std::string& filename)
		{
			//1.搭建服务器
			httplib::Client client(SERVER_IP, SERVER_PORT);
			//2.获取上传文件内容
			FileUtil fu(filename);
			std::string body;
			fu.GetContent(&body);
			//3. 填充内容
			httplib::MultipartFormData item;
			item.name = "file";
			item.content = body;
			item.filename = FileUtil(filename).FileName();
			item.content_type = "text/plain";

			//4.push进发送表
			httplib::MultipartFormDataItems items;
			items.push_back(item);
			auto res = client.Post("/upload", items);
			if (!res || res->status != 200)
			{
				return false;
			}

			return true;
		}
	private:
		std::string _obj_dir;//上传文件目录
		FileDatas* _data;
	};
}

你可能感兴趣的:(#云备份系统,linux,c++)