GitHub源码:智能云存储系统
目录
项目介绍
在网络飞速发展的今天,数据量越来越大,但是合适的网盘就显得尤为重要了,在这个前提下,开发了本项目。本项目主要是完成自动对指定目录监控并备份,且通过网页的方式浏览下载的功能。具体描述如下:
- 客户端对指定目录进行监控,如果目录下产生了新文件或者目录下的文件被修改了就自动备份到服务器上,基于http协议的put请求上传采用多线程,分块传输的方式,提高上传效率。
- 服务器基于httplib搭建HTTP服务器,给用户提供访问文件列表,上传文件等功能,采用多线程的方式测目录如果是太久没有访问的(热度低)文件,进行压缩处理,节省服务器磁盘空间。
- 用户通过浏览器访问服务器,浏览或者下载已经备份的文件。
流程框架
-
客户端
客户端通过三个模块实现:目录文件检测监控模块、文件上传备份模块、文件本分信息记录模块。
客户端流程图
-
服务端
服务端分为对客户端服务模块,文件压缩模块
服务端流程
客户端设计
-
功能
1、首先是有一个目录下文件检测的功能,判断其是否需要备份
2、对于需要备份的文件,分块上传到服务器上
-
设计
1、在程序运行环境下创建 backupinfo.txt 文件,用于记录文件最后大小和最后写入时间
2、程序一开始,就将backupinfo.txt中的信息读入到内存中,鉴别是否需备份。
3、对于需要备份的文件,基于http的PUT请求,采用多线程分块传输的方式上传到服务器上
4、备份成功后修改内存中的记录信息,在服务器返回状态为200 OK的时候,写入到backupinfo.txt中。
-
接口
class CloudClient
{
public:
CloudClient();
bool Run();
private:
//获取备份信息
bool GetBackupInfo();
//刷新备份信息
bool TouchBackupInfo();
//监听备份目录
bool BackupDirListen(const std::string& pathname);
//上传文件/文件备份
bool PutFileData(const std::string& filename);
//添加单个文件的etag
void AddFileBackInfo(const std::string& filename);
//获取单个文件etag
std::string GetFileEtag(const std::string& filename);
//文件是否需要备份
bool FileDateNeedBackup(const std::string& filename);
private:
//备份信息
std::unordered_map<std::string, std::string> backup_list_;
};
服务端设计
-
功能
1、对客户端的提供浏览已经备份的文件记录浏览,提供文件下载功能,提供文件上传功能
2、对服务器自身,为了节省磁盘空间,对于用户不经常访问的文件进行压缩处理,在需要下载时,进行解压缩处理。
-
设计
服务端的设计主要是两大模块,对客户端服务模块,一个是,文件上传后处理模块。
客户端服务模块:这个模块借用htttlib的接口实现了一个简单的http服务器。在服务端首先创建了一个目录mroot/,这个目录是相对于用户的一个根目录,该目录下有一个list/,这个list/是用户上传上来的文件保存的地方。在http服务器中分别实现了GET、PUT、POST三个请求方法的处理函数,当用户以GET方法请求时,返回用户已经上传的文件列表;以POST方法请求时,则是用户下载功能,返回用户要下载的文件,PUT则是用上传文件,成功上传后写入中
文件上传后处理模块:这个模块主要是为了节省服务器磁盘空间,当文件上传之后,如果用户不经常访问某文件,则会自动将文件进行压缩,到用户需要下载时再将文件进行解压缩出来。首先需要创建一个comconf.txt文件,用于记录文件名与压缩文件的映射,程序启动时,将该记录读入到内存之中,开始遍历目录,进行文件判断是否需要压缩,如果需要压缩,在压缩完成之和需要经文件名称与压缩文件名称堆的映射关系写入到内存中,等待整个目录遍历完成之后写入到文件中。用户下载时,就需要通过该映射关系从文件名找到该压缩文件。
两个模块多线程的方式实现。
-
接口
客户端服务模块实现:server.h
#include<iostream>
#include<boost/filesystem.hpp>
#include<sstream>
#include<unistd.h>
#include<fcntl.h>
#include<fstream>
#include "httplib.h"
#include "compressserver.h"
#define SERVER_ROOT_PATH "mroot"
#define SERVER_BACKUP_PATH "mroot/list"
#define SERVER_ADDR "0.0.0.0"
#define SERVER_PORT 9090
namespace hb = httplib;
namespace bf = boost::filesystem;
class Server
{
public:
Server();
bool Run();
private:
//展示文件列表
static void GetFileList(const hb::Request& req, hb::Response& res);
//获取文件数据
static void GetFileData(const hb::Request& req, hb::Response& res);
//文件上传
static void PutFileData(const hb::Request& req, hb::Response& res);
static bool RangeParse(std::string& range, int64_t& begin);
//文件备份
static void BackupFile(const hb::Request& req, hb::Response& res);
private:
hb::Server srv_;
};
文件压缩模块实现:compressserver.h
#pragma once
#include<iostream>
#include<unordered_map>
#include<string>
#include<sstream>
#include<vector>
#include<pthread.h>
#include<thread>
#include<fstream>
#include<boost/filesystem.hpp>
#include<boost/algorithm/string.hpp>
#include<sys/stat.h>
#include<unistd.h>
#include<sys/file.h>
#define COMPRESS_DIR "mroot/zip/"
#define GUNZIP_DIR "mroot/list"
#define COMMPRESS_FILE_CONF "comconf.txt"
#define HEAT_TIME 60
namespace bf = boost::filesystem;
//压缩服务
class CompressServer
{
public:
CompressServer();
~CompressServer();
//向外提供获取文件列表的功能
bool GetFileList(std::vector<std::string>& filelist);
//向外提供文件下载功能,对文件先进行解压,文件名---文件数据
bool DowanloadFile(std::string& file, std::string& body);
//对热度低的文件进行压缩,节省磁盘空间
bool LowHeatCompress();
bool SetFileData(std::string& file, const std::string& body, int64_t offest);
private:
//获取每次存储线程启动时,从文件读取列表信息
bool GetListConf();
//压缩完毕,将数据写入文件
bool SetListConf();
//文件目录检测
bool DirCheck();
//判断文件是否需要被压缩
bool IsNeedCompress(std::string filename);
//压缩文件
bool CompressFile(std::string& filename);
//解压缩文件
bool UnCommpressFile(std::string& filename);
bool GetGzpFile(std::string& name, std::string& gzname);
bool GetNormalFile(std::string& filename, std::string& body);
bool AddFileConf(std::string& file, const std::string& gzname);
private:
std::string file_dir_;
//保存文件列表,源文件名称,压缩包文件名称---文件映射列表
std::unordered_map<std::string, std::string> file_list_;
//文件读写时保护
pthread_rwlock_t rwlock_;
};
总体流程