当前位置: 首页 > news >正文

基于muduo库的图床云共享存储项目(四)

基于muduo库的图床云共享存储项目(四)

  • 文件列表功能实现
    • /api/myfiles&cmd=count 文件数量
      • 功能介绍
      • 代码实现
    • /api/myfiles&cmd=normal 文件列表
      • 功能介绍
      • 代码实现
  • 分享图片功能的实现
    • /api/sharepic?cmd=share 请求图片分享
      • 功能介绍
      • 代码实现
    • /api/sharepic?cmd=browse 请求浏览图片
      • 功能介绍
      • 代码实现
    • /api/sharepic?cmd=normal 我的图片分享
      • 功能介绍
      • 代码实现
    • /api/sharepic?cmd=cancel 取消图片分享
      • 功能介绍
      • 代码实现

上一章节我们实现了文件的上传以及秒传功能,接下来我们来实现人用户文件列表,现图片分享和文件删除功能。

文件列表功能实现

/api/myfiles&cmd=count 文件数量

对于文件列表,我们所需要考虑的因素就是一页可以存放多少个文件,然后将对应的的文件信息显示出来即可

功能介绍

请求URL

URLhttp://192.168.1.6/api/myfiles?cmd=count
请求方式POST
HTTP版本1.1
Content-Typeapplication/json

请求参数

参数名含义规则说明是否必须缺省值
tokentoken同上必填
user用户名称不能超过32个字符必填

返回结果参数说明

名称含义规则说明
code结果值0:验证成功
1:验证失败
total文件数量

处理逻辑

在这里插入图片描述

代码实现

api_myfile.h

#ifndef _API_MYFILES_H_
#define _API_MYFILES_H_
#include "api_common.h" 
// /api/myfiles&cmd=count
int ApiMyfiles(std::string &url, std::string &post_data, std::string &str_json);#endif

api_myfile.cc

#include "api_myfile.h"// 数据反序列化
int decodeCountJson(std::string &str_json, std::string &user_name, std::string &token) {bool res;Json::Value root;Json::Reader jsonReader;res = jsonReader.parse(str_json, root);if (!res) {LOG_ERROR << "parse reg json failed ";return -1;}int ret = 0;// 用户名if (root["user"].isNull()) {LOG_ERROR << "user null";return -1;}user_name = root["user"].asString();//密码if (root["token"].isNull()) {LOG_ERROR << "token null";return -1;}token = root["token"].asString();return ret;
}// 序列化数据
int encodeCountJson(int ret, int total, string &str_json) {Json::Value root;root["code"] = ret;if (ret == 0) {root["total"] = total; // 正常返回的时候才写入token}Json::FastWriter writer;str_json = writer.write(root);return 0;
}// 查询数据库,根据user_file_list来查询对应的文件数量
int getUserFilesCount(CDBConn *db_conn, string &user_name, int &count) {int ret = 0;// 封装 sql 语句// select count(*) from user_file_list where user_name = 'gantaotao';std::string sql_str = FormatString("select count(*) from user_file_list where user = '%s'", user_name.c_str());// 操作sql语句CResultSet *result_set = db_conn->ExecuteQuery(sql_str.c_str());if (result_set && result_set->Next()) {// 存在在返回count = result_set->GetInt("count(*)");LOG_INFO << "count: " << count;ret = 0;delete result_set;}  else {ret = -1;LOG_ERROR << "操作 " << sql_str << "失败";}return ret;
}// 获取对应的文件数量
int handleUserFilesCount(std::string &user_name, int &count) {// 获取对应的 sql 连接池CDBManager *db_manager = CDBManager::getInstance();CDBConn *db_conn = db_manager->GetDBConn("tuchuang_slave");AUTO_REL_DBCONN(db_manager, db_conn);int ret = getUserFilesCount(db_conn, user_name, count);return ret;
}int ApiMyfiles(std::string &url, std::string &post_data, std::string &str_json)
{char cmd[20]; std::string user_name;std::string token;int ret = 0;// 用户拥有的文件数量int total_count = 0;int start;// 一页的文件数量int count;// 解析url定义的参数,判断当前行为QueryParseKeyValue(url.c_str(), "cmd", cmd, NULL);if(strcmp(cmd, "count") == 0) {// 当前获取的是文件的数量操作// 首先进行反序列化操作if (decodeCountJson(post_data, user_name, token) < 0) {encodeCountJson(1, 0, str_json);LOG_ERROR << "decodeCountJson failed";return -1;}// 对token进行验证if (VerifyToken(user_name, token) < 0) {encodeCountJson(1, 0, str_json);LOG_ERROR << "VerifyToken failed";return -1;}// 然后获取对应的文件数量ret =  handleUserFilesCount(user_name, total_count);if(ret < 0) {encodeCountJson(1, 0, str_json);} else {encodeCountJson(0, total_count, str_json);}return ret;} else if (strcmp(cmd, "normal") == 0) {} else {encodeGetFileListFailedJson(str_json); LOG_ERROR << "un handle" << cmd; }
}
  • 在文件列表中,我们需要获取的就是用户拥有的文件数量,以及一页的文件数量,超过一页的限制以后就需要放置在下一页当中;
  • 其实整个逻辑也是跟前面一样的,首先反序列化解析数据,然后进行处理,获取文件的数量,本质就是去 mysql 数据库中查找当前用户所拥有的文件总数,在将对应的总数返回即可;

/api/myfiles&cmd=normal 文件列表

获取到对应的文件数量以后,此时就可以来获取文件列表了,他需要显示的数据如下所示:

在这里插入图片描述

功能介绍

请求URL

URLhttp://192.168.1.6/api/myfiles?cmd=normal
请求方式POST
HTTP版本1.1
Content-Typeapplication/json

请求参数

参数名含义规则说明是否必须缺省值
token令牌同上必填
user用户名称不能超过32个字符必填
count文件个数文件个数需大于0必填
start开始位置必填

返回结果参数说明

名称含义规则说明
files文件结果集“code”: 0正常,1失败
“count”: 返回的当前文件数量,比如2
“total”: 个人文件总共的数量
“user”: 用户名称,
“md5”: md5值,
“create_time”: 创建时间,
“file_name”: 文件名,
“share_status”: 共享状态, 0为没有共享, 1为共享
“pv”: 文件下载量,下载一次加1
“url”: URL,
“size”: 文件大小,
“type”: 文件类型
“type” :文件类型
“size” :文件大小

在这里插入图片描述

代码实现

api_myfile.cc

#include "api_myfile.h"// 数据反序列化
int decodeCountJson(std::string &str_json, std::string &user_name, std::string &token) {bool res;Json::Value root;Json::Reader jsonReader;res = jsonReader.parse(str_json, root);if (!res) {LOG_ERROR << "parse reg json failed ";return -1;}int ret = 0;// 用户名if (root["user"].isNull()) {LOG_ERROR << "user null";return -1;}user_name = root["user"].asString();//密码if (root["token"].isNull()) {LOG_ERROR << "token null";return -1;}token = root["token"].asString();return ret;
}//解析的json包
// 参数
// {
// "count": 2,
// "start": 0,
// "token": "3a58ca22317e637797f8bcad5c047446",
// "user": "gantaotao"
// }
int decodeFileslistJson(string &str_json, string &user_name, string &token,int &start, int &count) {bool res;Json::Value root;Json::Reader jsonReader;res = jsonReader.parse(str_json, root);if (!res) {LOG_ERROR << "parse reg json failed ";return -1;}int ret = 0;// 用户名if (root["user"].isNull()) {LOG_ERROR << "user null";return -1;}user_name = root["user"].asString();//密码if (root["token"].isNull()) {LOG_ERROR << "token null";return -1;}token = root["token"].asString();if (root["start"].isNull()) {LOG_ERROR << "start null";return -1;}start = root["start"].asInt();if (root["count"].isNull()) {LOG_ERROR << "count null";return -1;}count = root["count"].asInt();return ret;
}// 序列化数据
int encodeCountJson(int ret, int total, string &str_json) {Json::Value root;root["code"] = ret;if (ret == 0) {root["total"] = total; // 正常返回的时候才写入token}Json::FastWriter writer;str_json = writer.write(root);return 0;
}int encodeGetFileListFailedJson(string &str_json) {Json::Value root;root["code"] = 1;Json::FastWriter writer;str_json = writer.write(root);return 0;
}// 查询数据库,根据user_file_list来查询对应的文件数量
int getUserFilesCount(CDBConn *db_conn, string &user_name, int &count) {int ret = 0;// 封装 sql 语句// select count(*) from user_file_list where user_name = 'gantaotao';std::string sql_str = FormatString("select count(*) from user_file_list where user = '%s'", user_name.c_str());// 操作sql语句CResultSet *result_set = db_conn->ExecuteQuery(sql_str.c_str());if (result_set && result_set->Next()) {// 存在在返回count = result_set->GetInt("count(*)");LOG_INFO << "count: " << count;ret = 0;delete result_set;}  else {ret = -1;LOG_ERROR << "操作 " << sql_str << "失败";}return ret;
}// 获取对应的文件数量
int handleUserFilesCount(std::string &user_name, int &count) {// 获取对应的 sql 连接池CDBManager *db_manager = CDBManager::getInstance();CDBConn *db_conn = db_manager->GetDBConn("tuchuang_slave");AUTO_REL_DBCONN(db_manager, db_conn);int ret = getUserFilesCount(db_conn, user_name, count);return ret;
}// 获取文件列表
int getUserFileList(string cmd, string &user_name, int &start, int &count, string &str_json)
{LOG_INFO << "getUserFileList into";int ret = 0;int total = 0;string str_sql;CDBManager *db_manager = CDBManager::getInstance();CDBConn *db_conn = db_manager->GetDBConn("tuchuang_slave");AUTO_REL_DBCONN(db_manager, db_conn);//获取总的文件数量ret = getUserFilesCount(db_conn, user_name, total);if(ret < 0) {LOG_ERROR << "getUserFilesCount failed";Json::Value root;root["code"] = 1;Json::FastWriter writer;str_json = writer.write(root);return -1;}// 当前文件数量为0,正常返回if(0 == total) {Json::Value root;root["code"] = 0;root["count"] = 0;root["total"] = 0;Json::FastWriter writer;str_json = writer.write(root);return 0;}// 去user_file_list以及file_info查找对应的文件信息str_sql = FormatString("select user_file_list.*, file_info.url, file_info.size, file_info.type from file_info, \user_file_list where user = '%s' and file_info.md5 = user_file_list.md5 limit %d, %d ", user_name.c_str(), start, count);LOG_INFO << "执行:" << str_sql;CResultSet *result_set = db_conn->ExecuteQuery(str_sql.c_str());if (result_set) {Json::Value root;Json::Value files;root["code"] = 0;root["total"] = total; //即使 total 不为0, file_index为0int file_index = 0;// 和查询结果对比 total// files又是一个数组while (result_set->Next()){// 获取每一个文件的对应的信息Json::Value file;file["user"] = result_set->GetString("user");file["md5"] = result_set->GetString("md5");file["create_time"] = result_set->GetString("create_time");file["file_name"] = result_set->GetString("file_name");file["share_status"] = result_set->GetInt("shared_status");file["pv"] = result_set->GetInt("pv");file["url"] = result_set->GetString("url");file["size"] = result_set->GetInt("size");file["type"] = result_set->GetString("type");files[file_index] = file;file_index++;}// 查询完毕以后进行赋值root["files"] = files;root["count"] = file_index;Json::FastWriter writer;str_json = writer.write(root);LOG_INFO << "str_json: " << str_json;delete result_set;return 0;} else  {LOG_ERROR << "ExecuteQuery failed";Json::Value root;root["code"] = 1;Json::FastWriter writer;str_json = writer.write(root);return -1;}
}int ApiMyfiles(std::string &url, std::string &post_data, std::string &str_json)
{char cmd[20]; std::string user_name;std::string token;int ret = 0;// 用户拥有的文件数量int total_count = 0;int start;// 一页的文件数量int count;// 解析url定义的参数,判断当前行为QueryParseKeyValue(url.c_str(), "cmd", cmd, NULL);if(strcmp(cmd, "count") == 0) {// 当前获取的是文件的数量操作// 首先进行反序列化操作if (decodeCountJson(post_data, user_name, token) < 0) {encodeCountJson(1, 0, str_json);LOG_ERROR << "decodeCountJson failed";return -1;}// 对token进行验证if (VerifyToken(user_name, token) < 0) {encodeCountJson(1, 0, str_json);LOG_ERROR << "VerifyToken failed";return -1;}// 然后获取对应的文件数量ret =  handleUserFilesCount(user_name, total_count);if(ret < 0) {encodeCountJson(1, 0, str_json);} else {encodeCountJson(0, total_count, str_json);}return ret;} else if (strcmp(cmd, "normal") == 0) {//反序列化if(decodeFileslistJson(post_data, user_name, token, start, count) < 0) {encodeGetFileListFailedJson(str_json);LOG_ERROR << "decodeCountJson failed";return -1;}// 对token进行验证if (VerifyToken(user_name, token) < 0) {encodeGetFileListFailedJson(str_json);LOG_ERROR << "VerifyToken failed";return -1;}// 获取文件列表getUserFileList(cmd, user_name, start, count, str_json);} else {encodeGetFileListFailedJson(str_json); LOG_ERROR << "un handle" << cmd; }
}
  • 获取到文件的数量以后,我们就可以加载文件列表了,对于文件列表来说,就是需要获取到我们对应功能实现里面的数据库里面的信息。
  • 这儿需要注意的点就在于,获取文件列表的时候,序列化的时候采用的json的处理方式相比于之前存在一点儿差异,也就 files 是作为一个数组的存在,他里面又存在对应的 file , file 是 files 这个数组里面的一些元素。
    在这里插入图片描述

分享图片功能的实现

图片分享模块需要实现的就是将图片分享出去,别人是可以浏览的,同时我们也是可以取消分享的,他也依赖于一张新的表结构:

DROP TABLE IF EXISTS `share_picture_list`;
CREATE TABLE `share_picture_list` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '编号',
`user` varchar(32) NOT NULL COMMENT '文件所属用户',
`filemd5` varchar(256) NOT NULL COMMENT '文件md5',
`file_name` varchar(128) DEFAULT NULL COMMENT '文件名字',
`urlmd5` varchar(256) NOT NULL COMMENT '图床urlmd5',
`key` varchar(8) NOT NULL COMMENT '提取码',
`pv` int(11) DEFAULT '1' COMMENT '文件下载量,默认值为1,下载一次加1',
`create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '文件创建时间',
PRIMARY KEY (`id`),
KEY `idx_user_filemd5` (`user`, `filemd5`),
KEY `idx_urlmd5_user` (`urlmd5`, `user`)
) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8 COMMENT='图床文件列表';

我们会根据share_picture_list里面的 filemd5 找到对应的 file_info 需要对应文件,然后将对应的文件在分享出去,此时客户端就可以看见对应分享的文件了
在这里插入图片描述

/api/sharepic?cmd=share 请求图片分享

功能介绍

请求URL

URLhttp://192.168.1.6/api/sharepic?cmd=share
请求方式POST
HTTP版本1.1
Content-Typeapplication/json

请求参数

参数名含义规则说明是否必须缺省值
token令牌同上必填
user用户名称不能超过32个字符必填
md5md5值md5加密后的值必填
filename文件名称不能超过128个字符必填

返回结果参数说明

名称含义规则说明
code结果值0: 成功
1: 失败
4:token验证失败
urlmd5分享图片的标识取消分享时也要该标识

在这里插入图片描述

代码实现

api_sharepicture.h

#ifndef _API_SHAREPICTURE_H_
#define _API_SHAREPICTURE_H_
#include "api_common.h"
int ApiSharepicture(string &url, string &post_data, string &str_json);#endif

api_sharepicture.cc

#include "api_sharepicture.h"//解析的json包
int decodeSharePictureJson(string &str_json, string &user_name, string &token,string &md5, string &filename) {bool res;Json::Value root;Json::Reader jsonReader;res = jsonReader.parse(str_json, root);if (!res) {LOG_ERROR << "parse reg json failed ";return -1;}if (root["token"].isNull()) {LOG_ERROR << "token null";return -1;}token = root["token"].asString();if (root["user"].isNull()) {LOG_ERROR << "user null";return -1;}user_name = root["user"].asString();if (root["md5"].isNull()) {LOG_ERROR << "md5 null";return -1;}md5 = root["md5"].asString();if (root["filename"].isNull()) {LOG_ERROR << "filename null";return -1;}filename = root["filename"].asString();return 0;
}// 进行序列化
int encodeSharePictureJson(int ret, string urlmd5, string &str_json) {Json::Value root;root["code"] = ret;if (HTTP_RESP_OK == ret)root["urlmd5"] = urlmd5;Json::FastWriter writer;str_json = writer.write(root);return 0;
}//分享图片
// 当前设计的是这个文件是否存在不关注
int handleSharePicture(const char *user, const char *filemd5,const char *file_name, string &str_json) 
{// 获取数据库连接CDBManager *db_manager = CDBManager::getInstance();CDBConn *db_conn = db_manager->GetDBConn("tuchuang_slave");AUTO_REL_DBCONN(db_manager, db_conn);int ret = 0;string key;// 当前share_file_list里的urlmd5string urlmd5;urlmd5 = RandomString(32); // 这里我们先简单的,直接使用随机数代替 MD5的使用 可以使用token生成那个函数char create_time[TIME_STRING_LEN];time_t now;//获取当前时间now = time(NULL);strftime(create_time, TIME_STRING_LEN - 1, "%Y-%m-%d %H:%M:%S", localtime(&now));// 往对应的的share_file_list添加需要分享的这个文件string str_sql = FormatString("insert into share_picture_list (user, filemd5, file_name, urlmd5, `key`, pv, create_time) values ('%s', '%s', '%s', '%s', '%s', %d, '%s')", user, filemd5, file_name, urlmd5.c_str(), key.c_str(), 0, create_time);LOG_INFO << "执行:" << str_sql;if (!db_conn->ExecuteCreate(str_sql.c_str())) {LOG_ERROR << str_sql << " 操作失败";ret = -1;} else {ret = 0;}// if (ret == 0) {encodeSharePictureJson(HTTP_RESP_OK, urlmd5, str_json);} else {encodeSharePictureJson(HTTP_RESP_FAIL, urlmd5, str_json);}return 0;
}int ApiSharepicture(string &url, string &post_data, string &str_json) {char cmd[20];string user_name; //用户名string md5;       //文件md5码string urlmd5;string filename; //文件名字string token;int ret = 0;//解析命令QueryParseKeyValue(url.c_str(), "cmd", cmd, NULL);LOG_INFO << "cmd = " <<  cmd;if (strcmp(cmd, "share") == 0) //分享文件{ret = decodeSharePictureJson(post_data, user_name, token, md5, filename);if (ret == 0) {handleSharePicture(user_name.c_str(), md5.c_str(), filename.c_str(), str_json);} else {// 回复请求格式错误encodeSharePictureJson(HTTP_RESP_FAIL, urlmd5, str_json);}} else if (strcmp(cmd, "browse") == 0) //请求浏览图片{} else if (strcmp(cmd, "normal") == 0)  {}else {LOG_WARN << "un handle " << cmd;}return 0;}
  • 当前我们对于分享图片功能的实现,我们是没有提前进行判断的,直接就往share_file_list的表中插入了这条记录,最终返回对应文件的urlmd5即可。

/api/sharepic?cmd=browse 请求浏览图片

功能介绍

当前我们对于分享图片的功能已经进行了实现,那么对应分享出去的图片我们是需要可以进行浏览的,当前部分就是实现请求浏览图片的功能:

请求和应答

URLhttp://192.168.1.6/api/sharepic?cmd=browse
请求方式POST
HTTP版本 1.1
Content-Typeapplication/json

请求参数

参数名含义规则说明是否必须缺省值
urlmd5分享图片的标识必填

返回结果参数说明

名称含义规则说明
code结果值0:请求到 url 下载的 url
1:提取码错误
2:文件已经被删除
url图片下载地址
user分享者
time分享时间
pv浏览次数

在这里插入图片描述

代码实现

#include "api_sharepicture.h"//解析的json包
int decodeSharePictureJson(string &str_json, string &user_name, string &token,string &md5, string &filename) {bool res;Json::Value root;Json::Reader jsonReader;res = jsonReader.parse(str_json, root);if (!res) {LOG_ERROR << "parse reg json failed ";return -1;}if (root["token"].isNull()) {LOG_ERROR << "token null";return -1;}token = root["token"].asString();if (root["user"].isNull()) {LOG_ERROR << "user null";return -1;}user_name = root["user"].asString();if (root["md5"].isNull()) {LOG_ERROR << "md5 null";return -1;}md5 = root["md5"].asString();if (root["filename"].isNull()) {LOG_ERROR << "filename null";return -1;}filename = root["filename"].asString();return 0;
}int decodeBrowsePictureJson(string &str_json, string &urlmd5) {bool res;Json::Value root;Json::Reader jsonReader;res = jsonReader.parse(str_json, root);if (!res) {LOG_ERROR << "parse reg json failed ";return -1;}if (root["urlmd5"].isNull()) {LOG_ERROR << "urlmd5 null";return -1;}urlmd5 = root["urlmd5"].asString();return 0;
}// 进行序列化
int encodeSharePictureJson(int ret, string urlmd5, string &str_json) {Json::Value root;root["code"] = ret;if (HTTP_RESP_OK == ret)root["urlmd5"] = urlmd5;Json::FastWriter writer;str_json = writer.write(root);return 0;
}int encodeBrowselPictureJson(int ret, int pv, string url, string user,string time, string &str_json) {Json::Value root;root["code"] = ret;if (ret == 0) {root["pv"] = pv;root["url"] = url;root["user"] = user;root["time"] = time;}Json::FastWriter writer;str_json = writer.write(root);return 0;
}// 分享图片
// 当前设计的是这个文件是否存在不关注
int handleSharePicture(const char *user, const char *filemd5,const char *file_name, string &str_json) 
{// 获取数据库连接CDBManager *db_manager = CDBManager::getInstance();CDBConn *db_conn = db_manager->GetDBConn("tuchuang_slave");AUTO_REL_DBCONN(db_manager, db_conn);int ret = 0;string key;// 当前share_file_list里的urlmd5string urlmd5;urlmd5 = RandomString(32); // 这里我们先简单的,直接使用随机数代替 MD5的使用 可以使用token生成那个函数char create_time[TIME_STRING_LEN];time_t now;//获取当前时间now = time(NULL);strftime(create_time, TIME_STRING_LEN - 1, "%Y-%m-%d %H:%M:%S", localtime(&now));// 往对应的的share_file_list添加需要分享的这个文件string str_sql = FormatString("insert into share_picture_list (user, filemd5, file_name, urlmd5, `key`, pv, create_time) values ('%s', '%s', '%s', '%s', '%s', %d, '%s')", user, filemd5, file_name, urlmd5.c_str(), key.c_str(), 0, create_time);LOG_INFO << "执行:" << str_sql;if (!db_conn->ExecuteCreate(str_sql.c_str())) {LOG_ERROR << str_sql << " 操作失败";ret = -1;} else {ret = 0;}// if (ret == 0) {encodeSharePictureJson(HTTP_RESP_OK, urlmd5, str_json);} else {encodeSharePictureJson(HTTP_RESP_FAIL, urlmd5, str_json);}return 0;
}// 浏览图片的处理
int handleBrowsePicture(const char *urlmd5, string &str_json) {int ret = 0;string picture_url;string file_name;string user;string filemd5;string create_time;int pv = 0;CDBManager *db_manager = CDBManager::getInstance();CDBConn *db_conn = db_manager->GetDBConn("tuchuang_master");AUTO_REL_DBCONN(db_manager, db_conn);LOG_INFO << "urlmd5: " <<  urlmd5;// 执行sql语句,去对应的share_picture_list表中找这个图片string sql_cmd = FormatString( "select user, filemd5, file_name, pv, create_time from ""share_picture_list where urlmd5 = '%s'", urlmd5);LOG_INFO << "执行: " <<  sql_cmd;CResultSet * result_set = db_conn->ExecuteQuery(sql_cmd.c_str());// sql语句语句执行成功,构建我们需要的结果if (result_set && result_set->Next()) {user = result_set->GetString("user");filemd5 = result_set->GetString("filemd5");file_name = result_set->GetString("file_name");pv = result_set->GetInt("pv");create_time = result_set->GetString("create_time");delete result_set;} else {if (result_set) {delete result_set;}ret = -1;goto END;}// 通过对应的filemd5找到对应的文件MD5sql_cmd = FormatString("select url from file_info where md5 ='%s'", filemd5.c_str());LOG_INFO << "执行: " <<  sql_cmd;// 获取到对应的urlresult_set = db_conn->ExecuteQuery(sql_cmd.c_str());if (result_set && result_set->Next()) {picture_url = result_set->GetString("url");delete result_set;} else {if (result_set) {delete result_set;}ret = -1;goto END;}// 更新访问计数pv += 1;sql_cmd = FormatString( "update share_picture_list set pv = %d where urlmd5 = '%s'", pv, urlmd5);LOG_INFO << "执行: " <<  sql_cmd;if (!db_conn->ExecuteUpdate(sql_cmd.c_str())) {LOG_ERROR << sql_cmd << " 操作失败";ret = -1;goto END;}ret = 0;END:// 返回对应的结果if (ret == 0) {encodeBrowselPictureJson(HTTP_RESP_OK, pv, picture_url, user,create_time, str_json);} else {encodeBrowselPictureJson(HTTP_RESP_FAIL, pv, picture_url, user,create_time, str_json);}
}int ApiSharepicture(string &url, string &post_data, string &str_json) {char cmd[20];string user_name; //用户名string md5;       //文件md5码string urlmd5;string filename; //文件名字string token;int ret = 0;//解析命令QueryParseKeyValue(url.c_str(), "cmd", cmd, NULL);LOG_INFO << "cmd = " <<  cmd;if (strcmp(cmd, "share") == 0) //分享文件{ret = decodeSharePictureJson(post_data, user_name, token, md5, filename);if (ret == 0) {handleSharePicture(user_name.c_str(), md5.c_str(), filename.c_str(), str_json);} else {// 回复请求格式错误encodeSharePictureJson(HTTP_RESP_FAIL, urlmd5, str_json);}} else if (strcmp(cmd, "browse") == 0) //请求浏览图片{ret = decodeBrowsePictureJson(post_data, urlmd5);LOG_INFO << "post_data: " << post_data << ", urlmd5: " <<  urlmd5;if (ret == 0) {handleBrowsePicture(urlmd5.c_str(), str_json);} else {// 回复请求格式错误encodeSharePictureJson(HTTP_RESP_FAIL, urlmd5, str_json);}} else if (strcmp(cmd, "normal") == 0) {} else {LOG_WARN << "un handle " << cmd;}return 0;
}
  • 对于请求浏览图片来说,依赖于两个表,share_file_listfile_info这两个表,首先需要根据分享图片生成的urlmd5去对应的share_file_list当中找到这个图片文件的filemd5,然后再在对应的file_info这个表中获取到对应的文件 md5,然后就获取当前图片文件的url,后续通过这个url才可以进行浏览。
  • 这儿还需要注意的一个点是我们好需要更新对应的访问计数,每访问一次这个共享文件,对应的访问计数就需要进行++操作。

/api/sharepic?cmd=normal 我的图片分享

功能介绍

当前实现的就是获取到我的文件分享列表,其实跟我的文件列表新的实现过程相差不大。

请求和应答

URLhttp://192.168.1.6/api/sharepic?cmd=normal
请求方式POST
HTTP版本 1.1
Content-Typeapplication/json

请求参数

参数名含义规则说明是否必须缺省值
token令牌必填
user用户名称不能超过 32 个字符必填
count数量必填
start开始位置必填

返回结果参数说明

名称含义规则说明
files文件结果集“code”:0:正常;1:失败,
“count”: 2,// 分页返回数量,如果为 0 则不需要解析 files
“total”: 2,总的文件数量,
“user”: 用户名称,
“filemd5”: 文件 md5 值,
“urlmd5”: 图传共享时的 URL,
“create_time”: 创建时间,
“file_name”: 文件名,
“pv”: 文件浏览量,浏览一次加 1,
“size”: 文件大小。

在这里插入图片描述

代码实现

#include "api_sharepicture.h"//解析的json包
int decodeSharePictureJson(string &str_json, string &user_name, string &token,string &md5, string &filename) {bool res;Json::Value root;Json::Reader jsonReader;res = jsonReader.parse(str_json, root);if (!res) {LOG_ERROR << "parse reg json failed ";return -1;}if (root["token"].isNull()) {LOG_ERROR << "token null";return -1;}token = root["token"].asString();if (root["user"].isNull()) {LOG_ERROR << "user null";return -1;}user_name = root["user"].asString();if (root["md5"].isNull()) {LOG_ERROR << "md5 null";return -1;}md5 = root["md5"].asString();if (root["filename"].isNull()) {LOG_ERROR << "filename null";return -1;}filename = root["filename"].asString();return 0;
}int decodeBrowsePictureJson(string &str_json, string &urlmd5) {bool res;Json::Value root;Json::Reader jsonReader;res = jsonReader.parse(str_json, root);if (!res) {LOG_ERROR << "parse reg json failed ";return -1;}if (root["urlmd5"].isNull()) {LOG_ERROR << "urlmd5 null";return -1;}urlmd5 = root["urlmd5"].asString();return 0;
}//解析的json包
int decodePictureListJson(string &str_json, string &user_name, string &token,int &start, int &count) {bool res;Json::Value root;Json::Reader jsonReader;res = jsonReader.parse(str_json, root);if (!res) {LOG_ERROR << "parse reg json failed ";return -1;}if (root["token"].isNull()) {LOG_ERROR << "token null";return -1;}token = root["token"].asString();if (root["user"].isNull()) {LOG_ERROR << "user null";return -1;}user_name = root["user"].asString();if (root["start"].isNull()) {LOG_ERROR << "start null";return -1;}start = root["start"].asInt();if (root["count"].isNull()) {LOG_ERROR << "count null";return -1;}count = root["count"].asInt();return 0;
}// 进行序列化
int encodeSharePictureJson(int ret, string urlmd5, string &str_json) {Json::Value root;root["code"] = ret;if (HTTP_RESP_OK == ret)root["urlmd5"] = urlmd5;Json::FastWriter writer;str_json = writer.write(root);return 0;
}int encodeBrowselPictureJson(int ret, int pv, string url, string user,string time, string &str_json) {Json::Value root;root["code"] = ret;if (ret == 0) {root["pv"] = pv;root["url"] = url;root["user"] = user;root["time"] = time;}Json::FastWriter writer;str_json = writer.write(root);return 0;
}// 分享图片
// 当前设计的是这个文件是否存在不关注
int handleSharePicture(const char *user, const char *filemd5,const char *file_name, string &str_json) 
{// 获取数据库连接CDBManager *db_manager = CDBManager::getInstance();CDBConn *db_conn = db_manager->GetDBConn("tuchuang_slave");AUTO_REL_DBCONN(db_manager, db_conn);int ret = 0;string key;// 当前share_file_list里的urlmd5string urlmd5;urlmd5 = RandomString(32); // 这里我们先简单的,直接使用随机数代替 MD5的使用 可以使用token生成那个函数char create_time[TIME_STRING_LEN];time_t now;//获取当前时间now = time(NULL);strftime(create_time, TIME_STRING_LEN - 1, "%Y-%m-%d %H:%M:%S", localtime(&now));// 往对应的的share_file_list添加需要分享的这个文件string str_sql = FormatString("insert into share_picture_list (user, filemd5, file_name, urlmd5, `key`, pv, create_time) values ('%s', '%s', '%s', '%s', '%s', %d, '%s')", user, filemd5, file_name, urlmd5.c_str(), key.c_str(), 0, create_time);LOG_INFO << "执行:" << str_sql;if (!db_conn->ExecuteCreate(str_sql.c_str())) {LOG_ERROR << str_sql << " 操作失败";ret = -1;} else {ret = 0;}// if (ret == 0) {encodeSharePictureJson(HTTP_RESP_OK, urlmd5, str_json);} else {encodeSharePictureJson(HTTP_RESP_FAIL, urlmd5, str_json);}return 0;
}// 浏览图片的处理
int handleBrowsePicture(const char *urlmd5, string &str_json) {int ret = 0;string picture_url;string file_name;string user;string filemd5;string create_time;int pv = 0;CDBManager *db_manager = CDBManager::getInstance();CDBConn *db_conn = db_manager->GetDBConn("tuchuang_master");AUTO_REL_DBCONN(db_manager, db_conn);LOG_INFO << "urlmd5: " <<  urlmd5;// 执行sql语句,去对应的share_picture_list表中找这个图片string sql_cmd = FormatString( "select user, filemd5, file_name, pv, create_time from ""share_picture_list where urlmd5 = '%s'", urlmd5);LOG_INFO << "执行: " <<  sql_cmd;CResultSet * result_set = db_conn->ExecuteQuery(sql_cmd.c_str());// sql语句语句执行成功,构建我们需要的结果if (result_set && result_set->Next()) {user = result_set->GetString("user");filemd5 = result_set->GetString("filemd5");file_name = result_set->GetString("file_name");pv = result_set->GetInt("pv");create_time = result_set->GetString("create_time");delete result_set;} else {if (result_set) {delete result_set;}ret = -1;goto END;}// 通过对应的filemd5找到对应的文件MD5sql_cmd = FormatString("select url from file_info where md5 ='%s'", filemd5.c_str());LOG_INFO << "执行: " <<  sql_cmd;// 获取到对应的urlresult_set = db_conn->ExecuteQuery(sql_cmd.c_str());if (result_set && result_set->Next()) {picture_url = result_set->GetString("url");delete result_set;} else {if (result_set) {delete result_set;}ret = -1;goto END;}// 更新访问计数pv += 1;sql_cmd = FormatString( "update share_picture_list set pv = %d where urlmd5 = '%s'", pv, urlmd5);LOG_INFO << "执行: " <<  sql_cmd;if (!db_conn->ExecuteUpdate(sql_cmd.c_str())) {LOG_ERROR << sql_cmd << " 操作失败";ret = -1;goto END;}ret = 0;END:// 返回对应的结果if (ret == 0) {encodeBrowselPictureJson(HTTP_RESP_OK, pv, picture_url, user,create_time, str_json);} else {encodeBrowselPictureJson(HTTP_RESP_FAIL, pv, picture_url, user,create_time, str_json);}
}//获取共享图片个数
int getSharePicturesCount(CDBConn *db_conn,  string &user_name, int &count) {int ret = 0;// 从mysql加载if (DBGetSharePictureCountByUsername(db_conn, user_name, count) < 0) {LOG_ERROR << "DBGetSharePictureCountByUsername failed";return -1;}return ret;
}// 获取共享文件列表
void handleGetSharePicturesList(const char *user, int start, int count, string &str_json) 
{int ret = 0;char sql_cmd[SQL_MAX_LEN] = {0};CResultSet *result_set = NULL;int total = 0;int file_count = 0;Json::Value root;CDBManager *db_manager = CDBManager::getInstance();CDBConn *db_conn = db_manager->GetDBConn("tuchuang_slave");AUTO_REL_DBCONN(db_manager, db_conn);// 获取对应的文件总数total = 0;string temp_user = user;ret = getSharePicturesCount(db_conn, temp_user, total);if (ret < 0) {LOG_ERROR << "getSharePicturesCount failed";ret = -1;goto END;}// 执行对应的sql语句sprintf(sql_cmd,"select share_picture_list.user, share_picture_list.filemd5, share_picture_list.file_name,share_picture_list.urlmd5, share_picture_list.pv, \share_picture_list.create_time, file_info.size from file_info, share_picture_list where share_picture_list.user = '%s' and  \file_info.md5 = share_picture_list.filemd5 limit %d, %d", user, start, count);LOG_INFO << "执行: " <<  sql_cmd;result_set = db_conn->ExecuteQuery(sql_cmd);if (result_set) {// 遍历所有的内容// 获取大小Json::Value files;while (result_set->Next()) {Json::Value file;file["user"] = result_set->GetString("user");file["filemd5"] = result_set->GetString("filemd5");file["file_name"] = result_set->GetString("file_name");file["urlmd5"] = result_set->GetString("urlmd5");file["pv"] = result_set->GetInt("pv");file["create_time"] = result_set->GetString("create_time");file["size"] = result_set->GetInt("size");files[file_count] = file;file_count++;}if (file_count > 0) {root["files"] = files;}ret = 0;delete result_set;} else {ret = -1;}
END:if (ret != 0) {Json::Value root;root["code"] = 1;} else {root["code"] = 0;root["count"] = file_count;root["total"] = total;}str_json = root.toStyledString();LOG_INFO << "str_json: " << str_json;return;}int ApiSharepicture(string &url, string &post_data, string &str_json) {char cmd[20];string user_name; //用户名string md5;       //文件md5码string urlmd5;string filename; //文件名字string token;int ret = 0;//解析命令QueryParseKeyValue(url.c_str(), "cmd", cmd, NULL);LOG_INFO << "cmd = " <<  cmd;if (strcmp(cmd, "share") == 0) //分享文件{ret = decodeSharePictureJson(post_data, user_name, token, md5, filename);if (ret == 0) {handleSharePicture(user_name.c_str(), md5.c_str(), filename.c_str(), str_json);} else {// 回复请求格式错误encodeSharePictureJson(HTTP_RESP_FAIL, urlmd5, str_json);}} else if (strcmp(cmd, "browse") == 0) //请求浏览图片{ret = decodeBrowsePictureJson(post_data, urlmd5);LOG_INFO << "post_data: " << post_data << ", urlmd5: " <<  urlmd5;if (ret == 0) {handleBrowsePicture(urlmd5.c_str(), str_json);} else {// 回复请求格式错误encodeSharePictureJson(HTTP_RESP_FAIL, urlmd5, str_json);}} else if (strcmp(cmd, "normal") == 0) {int start = 0;int count = 0;ret = decodePictureListJson(post_data, user_name, token, start, count);if (ret == 0) {handleGetSharePicturesList(user_name.c_str(), start, count,  str_json);} else {// 回复请求格式错误encodeSharePictureJson(HTTP_RESP_FAIL, urlmd5, str_json);}}else {LOG_WARN << "un handle " << cmd;}return 0;}
  • 获取分享文件列表主要就是 handleGetSharePicturesList 这个接口的实现,其实逻辑也很简单,就是去对应的file_infoshare_picture_list查找到我们对应的需要的信息,然后返回在进行序列化返回对应的数据即可。

/api/sharepic?cmd=cancel 取消图片分享

功能介绍

当前实现的就是取消我们的对应文件分享的操作。

请求和应答

参数名含义规则说明是否必须缺省值
token令牌必填
urlmd5urlmd5必填

返回结果参数说明

名称含义规则说明
code结果值0: 成功
1: 失败

在这里插入图片描述

代码实现

int decodeCancelPictureJson(string &str_json, string &user_name,string &urlmd5) {bool res;Json::Value root;Json::Reader jsonReader;res = jsonReader.parse(str_json, root);if (!res) {LOG_ERROR << "parse reg json failed ";return -1;}if (root["user"].isNull()) {LOG_ERROR << "user null";return -1;}user_name = root["user"].asString();if (root["urlmd5"].isNull()) {LOG_ERROR << "urlmd5 null";return -1;}urlmd5 = root["urlmd5"].asString();return 0;
}int encodeCancelPictureJson(int ret, string &str_json) {Json::Value root;root["code"] = ret;Json::FastWriter writer;str_json = writer.write(root);return 0;
}
//取消分享文件
void handleCancelSharePicture(const char *user, const char *urlmd5,string &str_json) {int ret = 0;char sql_cmd[SQL_MAX_LEN] = {0};CDBManager *db_manager = CDBManager::getInstance();CDBConn *db_conn = db_manager->GetDBConn("tuchuang_master");AUTO_REL_DBCONN(db_manager, db_conn);//删除在共享图片列表的数据sprintf(sql_cmd, "delete from share_picture_list where user = '%s' and urlmd5 = '%s'", user, urlmd5);LOG_INFO << "执行: " <<  sql_cmd;if (!db_conn->ExecutePassQuery(sql_cmd)) {LOG_ERROR << sql_cmd << " 操作失败";encodeCancelPictureJson(HTTP_RESP_FAIL, str_json);} else {encodeCancelPictureJson(HTTP_RESP_OK, str_json);}            
}
  • 删除共享文件其实就是从对应的数据库中将文件删除就可以了,这个逻辑是非常简单的。

以上就是本节实现的内容,后续更新关注下一章节。

http://www.dtcms.com/a/359806.html

相关文章:

  • Luma 视频生成 API 对接说明
  • 编写一个用scala写的spark程序从本地读取数据,写到本地
  • 基于Matlab元胞自动机的强场电离过程模拟与ADK模型分析
  • 【Linux】模拟实现Shell(上)
  • 分享一个实用的B站工具箱(支持音视频下载等功能)
  • 【Canvas技法】绘制横向多色旗和竖向多色旗
  • 008.LangChain 输出解析器
  • 备份压缩存储优化方案:提升效率与节省空间的完整指南
  • 新手首次操作SEO核心要点
  • 线程池常见面试问答
  • 【Java实战⑩】Java 集合框架实战:Set与Map的奇妙之旅
  • 基于三维反投影矫正拼接视频
  • 数据结构(04)—— 栈和队列
  • 使用node-red+opencv+mqtt实现相机图像云端查看
  • 零基础入门AutoSar中的ARXML文件
  • Dify 从入门到精通(第 67/100 篇):Dify 的高可用性部署(进阶篇)
  • 从零开始写个deer-flow-mvp-第一天
  • 【C++】类和对象(一)
  • 【全功能图片处理工具详解】基于Streamlit的现代化图像处理解决方案
  • 二.Shell脚本编程
  • 微软开源TTS模型VibeVoice,可生成 90 分钟4人语音
  • 李宏毅NLP-13-Vocoder
  • 中级统计师-统计实务-第四章 专业统计
  • FPGA入门指南:从零开始的可编程逻辑世界探索
  • 【Proteus仿真】点亮小灯系列仿真——小灯闪烁/流水灯/交通灯
  • 常用的20个c++函数
  • 11.1.5 实现文件删除,共享和共享下载排行榜
  • 【GaussDB】排查应用高可用切换出现数据库整体卡顿及报错自治事务无法创建的问题
  • Photoshop - Ps 裁剪并拉直图片
  • 【C++详解】C++11(二) lambda表达式、类型分类、引⽤折叠、完美转发