在学习数据库编程总结了笔记,并分享出来。有问题请及时联系博主:Alliswell_WP,转载请注明出处。
09-数据库编程day06(案例开发)
目录:
一、学习目标
二、MongoDB复习
三、MongoDB API
0、复习API构造函数、连接函数、插入、删除
1、通过API修改数据和查询分析
2、通过API查询文档
3、通过API查询文档、内容解析、异常捕捉
四、案例开发(网盘-服务器端)
1、案例需求分析、模型设计
2、搭建框架
3、MySQL端登录实现
4、SQL注入问题解决
5、查看功能实现
6、MySQL侧实现上传功能
7、上传文件MongoDB侧实现
8、MySQL与MongoDB类的调用
9、上传测试成功
10、下载功能实现
11、总结
一、学习目标
1. api 实现查询功能.
2. 案例的数据模型设计
3. 了解案例实现的核心原理
4. 案例的程序框架搭建
5. 了解案例实现的过程
二、MongoDB复习
》体系结构:库—集合
集合:对应关系型数据库的表,键值对的组合
文档:键值对,json
》删库分2步:
○ 切库use dbname
○ 删库db.dropDatabase()
》文档的新增:
---insert
db.collection_name.insert(json)
--save 指定了_id时,相当于修改
--find
db.collection_name.find({cond},{show})
db.collection.aggregate() $group group By col1,col2 —— _id:{col1,col2}
--按位置,年龄分组,计算人数
db.Barca.aggregate({ $group:{ _id:{pos:"$pos",age:"$age"},count:{$sum:1} } })
--update
db.collection_name.update({query},{update},{upsert:false,multi:false})
--remove
db.collection_name.remove({query},{justOne:false})
--index
db.collection_name.ensureIndex({field:1})
db.collection_name.dropIndex({field:1})
三、MongoDB API
0、复习API构造函数、连接函数、插入、删除
1)构造函数
DBClientConnection(bool auto_connect, 0, double so_timeout);
auto_connect(IN):连接失败后自动重连
so_timeout(IN):非连接超时,tcp的读写超时
2)连接函数
bool connect(string server, &string errmsg);
返回值:成功/失败
server(IN):连接的服务器
errmsg(OUT):出错信息
》示例:
bool auto_connect = true;
double so_timeout = 3;
string host = "127.0.0.1";
string port = "27017";
string errmsg = "";
DBClientConnection pConn = new DBClientConnection(auto_connect, 0, so_timeout);
pConn->connect(host+":"+port, errmsg);
3)插入
void insert(const string &ns, BSONObj obj, int flags);
ns(IN):命名空间,db_name.collection_name
obj(IN):插入的列
flags(IN):详见API文档,默认填零即可
》示例:
BSONObj insert = BSON("uid"<<10001<<"name"<<"skean1017");
pConn->insert(db+"."+collection, insert, 0);
其效果相当于:
insert into shool.student (uid, name) values (10001, “skean1017″);
4)删除
void remove(const string &ns, Query query, bool justOne);
ns(IN):命名空间,db_name.collection_name
query(IN):查询条件
justOne(IN):是否只删除匹配的第一条
》示例:
Query query = QUERY("name"<<"skean1017");
pConn->remove(db+"."+collection, query, true);
其效果相当于:
delete from shool.student where name=”skean1017″;
1、通过API修改数据和查询分析
--修改
void update( const string &ns,Query query,BSONObj obj,bool upsert = false, bool multi = false );
○ ns 库名.集合名
○ obj BSON对象
○ upsert 如果条件不成立是否新增,默认false
○ multi 是否更新多条,默认false
》示例:
Query query = QUERY("uid"<<10001);
BSONObj obj = BSON("$set"<update(db+"."+collection, query, obj, false, false);
其效果相当于:
update shool.student set name=”habadog1203” where uid=10001;
--查询
virtual auto_ptr<DBClientCursor> query(const string &ns, Query query=Query() , int nToReturn = 0, int nToSkip = 0,const BSONObj *fieldsToReturn = 0, int queryOptions = 0 , int batchSize = 0 ) { checkConnection();
return DBClientBase::query( ns, query, nToReturn, nToSkip, fieldsToReturn, queryOptions , batchSize );
}
—auto_ptr<DBClientCursor> 智能指针,自动释放<>内部的内存数据
—cusor 游标
—DBClientCursor 类
○ more()如果为真,调用next是安全的
○ next()返回BSONObj 对象
——query函数参数
○ ns 库名.集合名
○ query 查询条件
○ nToReturn 返回记录数
○ nToSkip 跳过的记录数
○ fieldsToReturn 要返回的字段
》示例:
string db = "shool";
string collection = "student";
Query condition = QUERY("age"<<20);
int limit = 10;
int offset = 5;
BSONObj columns = BSON("uid"<<1<<"name"<<1);
auto_ptr cursor;
cursor = pConn->query(db+"."+collection, condition, limit, offset, columns, 0, 0);
其效果相当于:
select uid,name from shool.student where age=20 limit 5,10;
对结果集的操作:
int uid=0;
string name="";
while(cursor->more())
{
BSONObj p = cursor->next();
uid = p["uid"].Int();
name = p["name"].String();
count << uid << " " << name << endl;
}
2、通过API查询文档
--BSONObj对象
○ BSONElement getField(const StringData& name) const; 获得对应字段
思路:通过getField 获得BSONElement(元素)对象,调用String(),Number()精确获得各个值?
但是,如果有的数据没有age,这样调用有问题:
——解决:需要调用hasField(char*)或hasElement(char*)来判断是否有该元素
3、通过API查询文档、内容解析、异常捕捉
》解析文档流程:
》mongodb的api的异常处理
mongodb为我们提供了DBException异常类,如果有错误会进行抛出,我们可以通过try catch的方式捕捉该类错误,然后通过打印 what()显示错误详细信息.具体所在头文件: assert_util.h.除了捕获mongo提供的异常信息,还需要捕获标准库的错误信息,最后有一个兜底的所有异常捕捉.
使用方法:
catch( mongo::DBException& e ) {
printf("MONGO Exception(set): %s\n", e.what());
return -1;
}
catch (std::exception& e) {
printf("MONGO Exception(set): %s\n", e.what());
return -1;
}
catch (...){
printf(“MONGO Exception\n”);
return -1;
}
》头文件准备:
--在VS中更改main.cpp
#include <iostream> #include <string> #include <mongo/client/dbclient.h> using namespace std; using namespace mongo; int main(int argc,char *argv[]) { if (argc != 2){ cout << "./main 1|2|3|4 ---- 1-insert,2-remove,3-update,4-query" << endl; return -1; } int op = atoi(argv[1]); //构造连接 DBClientConnection conn(false,0,3); std::string errmsg; if (!conn.connect("localhost:27018", errmsg)){//模拟一下错误端口27018 cout << "connect to mongo err" << endl; //return -1; } cout << "connect ok" << endl; try{ if (op == 1){ //insert //第一种玩法 BSONObjBuilder b1; b1.append("id", 1); b1.append("name", "yekai");//{id:1,name:'yekai'} conn.insert("yekai.langzi", b1.obj()); //第二种玩法 BSONObjBuilder b2; b2 << "id" << 2 << "name" << "fuhongxue"; conn.insert("yekai.langzi", b2.obj()); //第三种玩法 conn.insert("yekai.langzi", BSON("id" << 3 << "name" << "luxiaojia")); //第四种玩法 Query ins("{id:4,name:'lixunhuan',age:50,info:{like:'drink',wuqi:'feidao'}}"); conn.insert("yekai.langzi", ins.obj); } else if (op == 2){ //remove //删除id》=2 {id:{$gte:2}} Query qry("{id:{$gte:2}}"); conn.remove("yekai.biancheng", qry); } else if (op == 3){ //update Query qry("{id:1}");//查询条件 //Query bobj("{$set:{name:'fuhongxue'}}");//更新的内容 Query bobj("{name:'fuhongxue'}");//更新的内容 conn.update("yekai.langzi", qry, bobj.obj); } else if (op == 4){ //query auto_ptr<DBClientCursor> cursor = conn.query("yekai.langzi", Query("{}")); while (cursor->more()){//判断是否有下一条 mongo::BSONObj obj = cursor->next();//取下一条记录,为BSONObj格式 //cout << obj << endl; //解析数据 cout << "id:" << obj.getField("id").Number() << ",name:" << obj.getField("name").String(); if (obj.hasElement("age")){//是否存在该元素 cout << ",age:" << obj.getField("age").Number(); } if (obj.hasElement("info")){ cout << ",info:{ like:" << obj["info"]["like"].String() << ",wuqi:" << obj["info"]["wuqi"].String()<<"}";//使用重载操作符[] } cout << endl; } } } catch (mongo::DBException& e) { printf("MONGO Exception(set): %s\n", e.what()); return -1; } catch (std::exception& e) { printf("MONGO STD Exception(set): %s\n", e.what()); return -1; } catch (...){ printf("MONGO Exception\n"); return -1; } return 0; }
原终端改变前后数据(>db.langzi.find())对比。
(将main.cpp传至Linux上,然后打开另一个终端重新编译,执行shell>./main 4)
四、案例开发(网盘-服务器端)
1、案例需求分析、模型设计
》需求总体描述
开发类似于网盘功能,支持文件(图片,视频,mp3等)的上传和下载(MongoDB的优势)。
》功能需求
支持多用户
1)用户的校验,必须是注册用户,用户名和密码正确才能上传和下载。(注册部分正常需要web前端开发,该案列不做注册部分功能,直接在mysql的用户表增加记录即可)。
2)查看登陆用户上传的文件信息。(支持命令行的方式查看即可,不需要做web前端),实现管理台。
3)上传文件
4)下载上传过的文件到本地。
5)删除上传的文件。(可根据情况是否添加,不是必须)
》技术实现要求
Mysql+mongo
用mysql存储用户的信息,文件上传和下载的对应关系(本地和mongo中文件的对应关系)
Mongo存放文件。
》流程
需求接收-需求分析-概要设计-详细设计-编码-测试-上线-维护-------------下线
》可行性分析:
工期评估 人月
技术可行性:
○ BSONObj storeFile( const string& fileName , const string& remoteName="" , const string& contentType=""); 上传GridFS
○ gridfs_offset write( const string& where ) const; 下载GridFile
功能设计,模块设计,模型设计
》设计功能:
○ 用户验证
○ 上传
○ 下载
○ 查看
○ 删除(二期)
》模块设计:
○ 设计2个类
▪ mysql 操作mysql数据库 用户验证,保存文件信息,查询文件信息
▪ mongo 操作mongo数据库 存文件,下载文件
》模型设计:
○ 参考功能
○ 用户验证 设计用户信息表
用户信息表:用户id,用户姓名,密码,手机号,公司,邮箱,备注
create table t_user_info( user_id varchar(30),
user_name varchar(50),
pass_word varchar(16),
remark varchar(100)
);
○ 文件信息查看设计文件信息表(mysql)
文件信息表:本地文件名,文件类型,大小,上传时间,修改时间,下载次数,用户id,mongo文件名,备注
create table t_file_info(
file_id int primary key auto_increment,
local_file_name varchar(50),
mongo_file_name varchar(50),
file_size int,
upload_date timestamp,
user_id varchar(30),
remark varchar(100)
);
打开VS2015,新建项目:选择“Visusl C++”,右侧选择“空项目”,名称:ods,位置改为project所在目录(我的为 F:\Download\06-数据库编程day06(案例开发)\4-源码\project);
创建成功后,在“ods”右键选择“属性”,选择“VC++目录”进行配置:选择“包含目录”,在其后加入到include一级的目录(最好是相对路径,我的为 ..\..\mongo\include);
在“ods”右键添加源文件:main.cpp,然后编写代码。
》建库建表(Linux登录MySQL):
shell>mysql -u root -p(输入密码)
mysql> show databases;
mysql> create database ods character set utf8;(建库:ods—online database store)
mysql> use ods;(切库)
mysql> create table t_user_info( user_id varchar(30), user_name varchar(50), pass_word varchar(16), remark varchar(100) );
mysql> create table t_file_info( file_id int primary key auto_increment, local_file_name varchar(50), mongo_file_name varchar(50), file_size int, upload_date timestamp, user_id varchar(30), remark varchar(100) );
2、搭建框架
》(管理台)设计指令:
-上传upload srcfile mongofile
-下载download mongofile desfile
-查看 list
-退出 quit
-删除 delete mongofile localfile(二期)
》编写main.cpp
#include <iostream> #include <vector> #include <string> using namespace std; void splitString(const char *Src, char delim, vector<string> &vsplit) { string tmp = Src; vsplit.clear(); int index = 0; size_t last = 0; last = tmp.find_first_not_of(delim, last);//找到第一个不为分隔符的字符 index = tmp.find_first_of(delim, last);//找到第一个分隔符 while (index != string::npos)//npos代表字符串的结尾 { string target = tmp.substr(last, index - last); vsplit.push_back(target); //last = index +1; last = tmp.find_first_not_of(delim, index); index = tmp.find_first_of(delim, last); } if (index == string::npos && tmp.length() > last)//到末尾了,如果整个长度大于last坐标,说明还有最后一个字符要放到vector { vsplit.push_back(tmp.substr(last)); } #if 1 cout << vsplit.size() << endl; for (size_t i = 0; i < vsplit.size(); i++) { cout << "i=" << i << "," << vsplit[i].c_str() << endl; } #endif } /* - 上传 upload srcfile mongofile - 下载 download mongofile desfile - 查看 list - 退出 quit 删除 delete mongofile localfile(二期) */ int main(int argc,char *argv[]) { if (argc != 3){ cout << "./main user passwd" << endl; return -1; } string line; vector<string> vCmd; while (1){//进入管理台 cout << "ods>"; getline(cin, line);//获取行,指令 splitString(line.c_str(), ' ', vCmd);//拆分命令 if (vCmd[0].compare("quit") == 0){ //quit cout << "bye bye" << endl; break; } else if (vCmd[0].compare("upload") == 0){ //上传 } else if (vCmd[0].compare("download") == 0){ //下载 } else if (vCmd[0].compare("list") == 0){ //查看 } } return 0; }
shell>mkdir day06
上传main.cpp至day06文件夹下
shell>g++ main.cpp -o main
shell>./main 11 22
ods>list
3、MySQL端登录实现
shell>locate mysql.h(然后把/usr/include的mysql目录及其下文件下载到project目录下,然后在ods的属性页的“VC++”目录,包含目录,添加:..\..\mysql)
在VS的“ods”处右键“添加类”,然后保持默认(左侧选择“Visual C++”下的“C++”,右侧C++类),点击“添加”;类名输入:CCMysql,点击“完成”,会生成CMysql.h和CMysql.cpp:
》添加用户和密码:
mysql> desc t_user_info;
mysql> insert into t_user_info values('yekai','叶开','123','bianchenglangzi');
mysql> insert into t_user_info values('fuhongxue','傅红雪','456','bianchenglangzi');
编写CMysql.h
#pragma once class CCMysql { public: CCMysql(); int UserLogin(const char *User,const char *Passwd); ~CCMysql(); };
编写CMysql.cpp
#include "CMysql.h" #include <stdio.h> #include <stdlib.h> #include <string.h> #include <mysql.h> MYSQL *mysql = NULL; CCMysql::CCMysql() { mysql = mysql_init(NULL); if (mysql == NULL){ printf("mysql init err"); exit(1); } mysql = mysql_real_connect(mysql, "localhost", "root", "123", "ods", 0, NULL, 0); if (mysql == NULL){ printf("mysql connect err"); exit(1); } } CCMysql::~CCMysql() { if (mysql){ mysql_close(mysql); } } //用户登陆 int CCMysql::UserLogin(const char *User, const char *Passwd) { //用户名和密码匹配 //执行该sql:select * from t_user_info where user_id='yekai' and pass_word='123'; //如果有结果集,代表匹配 char rSql[512] = { 0 }; sprintf(rSql, "select user_id from t_user_info where user_id='%s' and pass_word='%s'", User, Passwd); printf("%s\n", rSql); if (mysql_query(mysql, rSql)){ printf("mysql exe err:%s\n", rSql); return -1; } MYSQL_RES *result = mysql_store_result(mysql);//取结果集 if (result != NULL){//该指针为空并非代表准确,有结果集,但结果集没有记录 return (int)result->row_count; } return 0;// 代表结果不匹配 }
》编译:
shell>touch makefile
shell>vi makefile
#SrcFiles=$(wildcard *.c) IncPath=/usr/include/mysql LibPath=/usr/lib64/mysql PubLib=-lmysqlclient -lstdc++ -ldl -lpthread -lrt all:main main:main.cpp CMysql.cpp gcc -o $@ $^ -I$(IncPath) -L$(LibPath) $(PubLib) clean: -rm -f main
》扩展:SQL注入
mysql> ./main yekai " 0' or '1=1"
4、SQL注入问题解决
》分析:SQL注入在于登录语句中含有or,所以如果判断密码处含有or,报错。
#include "CMysql.h" #include <stdio.h> #include <stdlib.h> #include <string.h> #include <mysql.h> MYSQL *mysql = NULL; CCMysql::CCMysql() { mysql = mysql_init(NULL); if (mysql == NULL){ printf("mysql init err"); exit(1); } mysql = mysql_real_connect(mysql, "localhost", "root", "123", "ods", 0, NULL, 0); if (mysql == NULL){ printf("mysql connect err"); exit(1); } } CCMysql::~CCMysql() { if (mysql){ mysql_close(mysql); } } //用户登陆 int CCMysql::UserLogin(const char *User, const char *Passwd) { //用户名和密码匹配 //执行该sql:select * from t_user_info where user_id='yekai' and pass_word='123'; //如果有结果集,代表匹配 if (strstr(Passwd, " or ")){ printf("zhe yang bu hao!\n"); return 0; } char rSql[512] = { 0 }; sprintf(rSql, "select user_id from t_user_info where user_id='%s' and pass_word='%s'", User, Passwd); printf("%s\n", rSql); if (mysql_query(mysql, rSql)){ printf("mysql exe err:%s\n", rSql); return -1; } MYSQL_RES *result = mysql_store_result(mysql);//取结果集 if (result != NULL){//该指针为空并非代表准确,有结果集,但结果集没有记录 return (int)result->row_count; } return 0;// 代表结果不匹配 }
5、查看功能实现
CMysql.h中增加:
int ListFileInfo(const char *User);
CMysql.cpp中增加:
int CCMysql::ListFileInfo(const char *User) { //select * from t_file_info where user_id='yekai'; //执行上面的sql,显示结果集 char rSql[512] = { 0 }; sprintf(rSql, "select * from t_file_info where user_id='%s'", User); if (mysql_query(mysql, rSql)){ printf("query err:%s\n", rSql); return -1; } MYSQL_RES *result = mysql_store_result(mysql);//取结果集 if (result != NULL){//该指针为空并非代表准确,有结果集,但结果集没有记录 MYSQL_ROW row; unsigned int num_fields; unsigned int i; num_fields = mysql_num_fields(result); while ((row = mysql_fetch_row(result))) { unsigned long *lengths; lengths = mysql_fetch_lengths(result); for (i = 0; i < num_fields; i++) { printf("%s\t", row[i] ? row[i] : "NULL"); } printf("\n"); } } return 0; }
main.cpp中增加:
#include "CMysql.h"
else if (vCmd[0].compare("list") == 0){ //查看 //cout << vCmd[0] << endl; cmysql.ListFileInfo(argv[1]); }
mysql> insert into t_file_info(local_file_name,mongo_file_name,file_size,user_id,remark) ('xxx.11','yyy.11',1024,'yekai','upload sucess');
mysql> insert into t_file_info(local_file_name,mongo_file_name,file_size,user_id,remark) ('xxx.22','yyy.2',10240,'fuhongxue','upload sucess');
打开另一个终端,查看:
6、MySQL侧实现上传功能
》查看文件信息,看需要上传哪些信息
(t_file_info表增加status状态信息)
mysql> alter table t_file_info add column status varchar(2);
》上传设计:
第一步:
先插入对应关系,状态填0,代表正在上传,
第二步:
mongo上传文件
第三步:
更新文件对应关系,文件大小,status 上传成功 1,remark 上传成功
上传和下载一块做:(打开另一个终端方便查看,先输入update语句测试)
CMysql.h中增加:
int UploadFile(const char *User,const char *LocalFile,const char *MongoFile); int UpdateFileInfo(myulong FileSize, const char *User, const char *LocalFile, const char *MongoFile);
CMysql.cpp中增加:
int CCMysql::UploadFile(const char *User, const char *LocalFile, const char *MongoFile) { //insert into t_file_info(local_file_name, mongo_file_name, file_size, user_id,status, remark) //values('xxx.11', 'yyy.11', 1024, 'yekai', '0','upload sucess'); //需要执行上述insert语句,代表上传文件状态 char rSql[512] = { 0 }; sprintf(rSql, "insert into t_file_info(local_file_name, mongo_file_name, file_size, user_id,status, remark)" "values('%s', '%s', 0, '%s', '0','uploading')", LocalFile, MongoFile, User); if (mysql_query(mysql, rSql)){ printf("run upload err:%s\n", rSql); return -1; } return 0; } int CCMysql::UpdateFileInfo(myulong FileSize, const char *User, const char *LocalFile, const char *MongoFile) { //update t_file_info set file_size=1011,status='1',remark='upload sucess' //where user_id='yekai' and local_file_name='xxx.11' and mongo_file_name='yyy.11'; char rSql[512] = { 0 }; sprintf(rSql, "update t_file_info set file_size=%lld,status='1',remark='upload sucess'" "where user_id='%s' and local_file_name='%s' and mongo_file_name='%s'", FileSize, User, LocalFile, MongoFile); if (mysql_query(mysql, rSql)){ printf("run update err:%s\n", rSql); return -1; } return 0; }
main.cpp中增加:
else if (vCmd[0].compare("upload") == 0){ //上传 cout << "upoload:" << vCmd[1] << "," << vCmd[2] << endl; //1. mysql 执行 insert cmysql.UploadFile(argv[1], vCmd[1].c_str(), vCmd[2].c_str()); //2. mongo 上传 文件 //3. mysql 执行 update //stat cmysql.UpdateFileInfo(llsize, argv[1], vCmd[1].c_str(), vCmd[2].c_str()); }
7、上传文件MongoDB侧实现
在VS的“ods”处右键“添加类”,然后保持默认(左侧选择“Visual C++”下的“C++”,右侧C++类),点击“添加”;类名输入:CCMongo,点击“完成”,会生成CMongo.h和CMongo.cpp:
CMongo.h中增加:
#pragma once #include <iostream> #include <mongo/client/dbclient.h> #include <string> using namespace std; class CCMongo { public: CCMongo(); int UploadFile(const char *LocalFile, const char *MongoFile); ~CCMongo(); };
CMongo.cpp中增加:
#include "CMongo.h" #include <stdlib.h> using namespace mongo; DBClientConnection *conn = NULL; CCMongo::CCMongo() { conn = new DBClientConnection(false, 0, 3); std::string errmsg; if (!conn->connect("localhost", errmsg)){ cout << "connect to mongo err:" << errmsg << endl; exit(1); } } CCMongo::~CCMongo() { if (conn){ delete conn; conn = NULL; } } mongoulong CCMongo::UploadFile(const char *LocalFile, const char *MongoFile) { //构造 GridFS对象 mongo::GridFS gfs(*conn, "ods"); //上传文件 gfs.storeFile(LocalFile, MongoFile); return 0; }
8、MySQL与MongoDB类的调用
》获取文件大小及更改:
CMongo.h中增加及修改:
#pragma once #include <iostream> #include <mongo/client/dbclient.h> #include <string> using namespace std; typedef unsigned long long mongoulong; class CCMongo { public: CCMongo(); mongoulong UploadFile(const char *LocalFile, const char *MongoFile); ~CCMongo(); };
CMongo.cpp中增加及修改:
#include "CMongo.h" #include <stdlib.h> using namespace mongo; DBClientConnection *conn = NULL; CCMongo::CCMongo() { conn = new DBClientConnection(false, 0, 3); std::string errmsg; if (!conn->connect("localhost", errmsg)){ cout << "connect to mongo err:" << errmsg << endl; exit(1); } } CCMongo::~CCMongo() { if (conn){ delete conn; conn = NULL; } } mongoulong CCMongo::UploadFile(const char *LocalFile, const char *MongoFile) { //构造 GridFS对象 mongo::GridFS gfs(*conn, "ods"); //上传文件 mongo::BSONObj obj = gfs.storeFile(LocalFile, MongoFile); //GridFile findFile( BSONObj query ) const; return gfs.findFile(obj).getContentLength();//返回文件大小 //return 0; }
main.cpp中增加:
#include "CMongo.h" else if (vCmd[0].compare("upload") == 0){ //上传 cout << "upoload:" << vCmd[1] << "," << vCmd[2] << endl; //1. mysql 执行 insert cmysql.UploadFile(argv[1], vCmd[1].c_str(), vCmd[2].c_str()); //2. mongo 上传 文件 myulong llsize =cmongo.UploadFile(vCmd[1].c_str(), vCmd[2].c_str()); //3. mysql 执行 update //stat 也可以使用其获取文件大小 cmysql.UpdateFileInfo(llsize, argv[1], vCmd[1].c_str(), vCmd[2].c_str()); }
9、上传测试成功
makefile中更改:
#SrcFiles=$(wildcard *.c) IncPath=-I/usr/include/mysql -I/home/itcast/driver/mongo/include -I/home/itcast/driver/boost/include LibPath=-L/usr/lib64/mysql -L/home/itcast/driver/boost/lib -L/home/itcast/driver/mongo/lib PubLib=-lmysqlclient -ldl -lpthread -lrt -lmongoclient -lboost_thread -lboost_filesystem -lboost_program_options all:main main:main.cpp CMysql.cpp CMongo.cpp g++ -o $@ $^ $(IncPath) $(LibPath) $(PubLib) clean: -rm -f main
上传文件后重新编译
上传一张图片到day06后测试(如:ywbg.jpg)
打开另一个终端,登录mysql查看是否上传成功:
再打开第三个终端,登录MongoDB查看mongo端是否上传成功
10、下载功能实现
CMongo.h中增加:
int downloadFile(const char *MongoFile,const char *DesFile);
CMongo.cpp中增加:
int CCMongo::downloadFile(const char *MongoFile, const char *DesFile) { //通过gridfs 查找文件获得 gridfile 对象,write 就ok了 //构造 GridFS对象 mongo::GridFS gfs(*conn, "ods"); gfs.findFile(MongoFile).write(DesFile); return 0; }
main.cpp中增加
else if (vCmd[0].compare("download") == 0){ //下载 cout << "download:" << vCmd[1] << "," << vCmd[2] << endl; cmongo.downloadFile(vCmd[1].c_str(), vCmd[2].c_str()); }
上传文件,编译登录:
1)测试下载文件(先测试下载一张图片,如:刚才上传的ywbg.jpg)
另打开一个终端,查看是否下载成功:
将图片(下载)到本地Windows系统查看,(点击)看是否正常在Windows显示:
2)测试下载文件(先上传一部电影到day06,然后测试下载一部电影,如:hzw763.mp4)
再打开一个终端(第2个终端),切换到day06目录下,查看文件大小。然后登录MongoDB(当前只有之前上传成功的图片ywbg.jpg)
然后在原终端(即登录yekai 123)上传文件
然后打开第三个终端,登录mysql查看文件上传状态:(注意:此时文件大小为0!)
等待原终端(即登录yekai 123)上传成功:(出现ods> 即上传成功)
在之前打开的第3个终端(登录MySQL那个)查看文件上传状态:
查看第2个终端(登录MongoDB的那个)查看文件上传情况:
测试下载:
在原终端(即登录yekai 123)下载hzw763.mp4
查看第2个终端(登录MongoDB的那个,退出quit,然后查看)查看文件下载情况:
将电影(下载)到本地Windows系统查看,(点击)看是否正常在Windows播放。
11、总结
1)MySQL库和MongoDB库本身没有关系,是通过上传下载建立的联系。
2)MD5,MongoDB上传成功后会生成一个md5,可以通过md5去判断在当前文件夹文件是否已经下载。
3)删除(二期),在MySQL和MongoDB两个数据库都要删除,在两个数据库都留一个接口,根据命令行设计删除指令,然后在main函数调用一下。
在学习数据库编程总结了笔记,并分享出来。有问题请及时联系博主:Alliswell_WP,转载请注明出处。