项目描述
一个用户可以通过浏览器上传视频,且对自己上传的视频进行管理,而其他用户可以通过浏览器观看视频。
概要设计
采用不太严谨的MVC框架。此项目分模块进行设计——数据管理模块:对数据进行统一管理,外界只能通过此模块访问;用户界面/前端界面模块:实现用户交互,提供前端界面;业务处理模块:接收前端请求进行处理完成用户的需求。
技术调研
socket、http、tcp、json、mysql、前端三剑客(html、css、js)
详细设计
数据管理模块
1.数据存储
采用MySQL数据库——免费,采用c/s架构,可以远程访问以及有统一接口,安全便于扩展。
数据库表的设计: 视频信息表:视频id、视频名称、视频描述、上传时间、视频文件路径、封面图路径。
create database if not exists vod_system;
use vod_system;
create table if not exists tb_video(
id int primary key auto_increment,
name varchar(32),
vdesc text,
video_url varchar(255),
image_url varchar(255),
ctime datetime);
insert tb_video values(null,"飞机大战","这是一部烂片",
"/video/plane.mp4","/image/plane.jpg",now());
2.封装实现数据库访问类
该类提供视频信息的增删改查(所有视频/单个视频); 数据库表的访问类的实现
1.了解mysql的c语言库接口
1.定义mysql句柄 2.初始化mysql句柄 3.连接mysql服务器 4.设置客户端字符编码集 5.切换选择数据库 6.执行语句(库,表,数据操作—sql语句的执行)增,删,改–只要语句执行成功,就表示完成了查-需要执行语句成功后对数据进行操作 ①.将查询结果保存到本地 ②.获取保存的结果集中的数据条数和列数3.遍历逐条取出结果集中的每一条数据4.释放结果集 7.关闭句柄,释放资源 8.获取某个接口执行失败原因的接口
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <mysql/mysql.h>
int main()
{
MYSQL *mysql = NULL;
mysql = mysql_init(NULL);
if(mysql == NULL)
{
printf("mysql init error!\n");
return -1;
}
if(mysql_real_connect(mysql,"127.0.0.1","root","ljl12138",
"vod_system",0,NULL,0)==NULL)
{
printf("connect mysql failed:%s\n", mysql_error(mysql));
return -1;
}
int ret;
ret = mysql_set_character_set(mysql,"utf8");
if(ret != 0)
{
printf("set character failed:%s\n",mysql_error(mysql));
return -1;
}
char *select = "select * from tb_video;";
ret = mysql_query(mysql,select);
if(ret != 0)
{
printf("query sql failed:%s\n", mysql_error(mysql));
return -1;
}
MYSQL_RES *res = mysql_store_result(mysql);
if(res == NULL)
{
printf("store result failed:%s\n",mysql_error(mysql));
return -1;
}
int row_num = mysql_num_rows(res);
int col_num = mysql_num_fields(res);
int i = 0;
for(i = 0;i<row_num;++i)
{
MYSQL_ROW row = mysql_fetch_row(res);
int j = 0;
for(j = 0; j<col_num; ++j)
{
printf("%s\t",row[j]);
}
printf("\n");
}
mysql_free_result(res);
mysql_close(mysql);
return 0;
}
jsoncpp的基本使用:
实现json格式的序列化与反序列化功能
json数据类型:对象 {} ,字符串,整数,布尔,数组[]。
{“学生”:1001,“姓名”:“张三”,“年龄”:18,“婚否”:false,“成绩”:[88,77,66]},
Json::Value 中间数据对象; val[“学号”] = 1001;
Json::Writer 序列化对象,将Json::Value中的各个数据序列化为字符串; Json::Writer 是基类一般使用它的子类:StyledWrite/FastWriter,后者为整行形式,会去掉空行,空格;前者为会添加换行,空格之类的。 接口: std::string StyledWriter::write(val),将val按照json序列化格式序列化为字符串将其返回。
Json::Reader 反序列化对象,将一个json格式字符转换为Json::Value; Reader::parse(const std::string &str,Json::Value &val) 将str进行反序列化,将其反序列化之后的结果放入val中,通过val形式获取值。
在安装使用json时需要先进行gcc的升级:gcc升级及jsoncpp安装
3.数据管理模块代码
因为表中字段有多个,所以使用json序列化将多个字段整合成一个参数传递起来会方便很多。
#include <iostream>
#include <mysql/mysql.h>
#include <jsoncpp/json/json.h>
#include <mutex>
namespace vod_system
{
#define MYSQL_HOST "127.0.0.1"
#define MYSQL_USER "root"
#define MYSQL_PASS "ljl12138"
#define MYSQL_NAME "vod_system"
static MYSQL *MysqlInit()
{
MYSQL *mysql = mysql_init(NULL);
if(mysql == NULL)
{
std::cout<<"mysql init failed!\n";
return NULL;
}
if(mysql_real_connect(mysql,MYSQL_HOST,MYSQL_USER,
MYSQL_PASS,MYSQL_NAME,0,NULL,0)==NULL)
{
std::cout<<mysql_error(mysql)<<std::endl;
mysql_close(mysql);
return NULL;
}
if(mysql_set_character_set(mysql,"utf8")!=0)
{
std::cout<<mysql_error(mysql)<<std::endl;
mysql_close(mysql);
return NULL;
}
return mysql;
}
static void MysqlRelease(MYSQL *mysql)
{
if(mysql != NULL)
{
mysql_close(mysql);
}
return;
}
static bool MysqlQuery(MYSQL *mysql, const std::string sql)
{
int ret = mysql_query(mysql,sql.c_str());
if(ret != 0)
{
std::cout<<sql<<std::endl;
std::cout<<mysql_error(mysql)<<std::endl;
return false;
}
return true;
}
class TableVod
{
private:
MYSQL *_mysql;
std::mutex _mutex;
public:
TableVod()
{
_mysql = MysqlInit();
if(_mysql == NULL)
{
exit(0);
}
}
~TableVod()
{
MysqlRelease(_mysql);
}
bool Insert(const Json::Value &video)
{
const char* name = video["name"].asCString();
const char* vdesc = video["vdesc"].asCString();
const char *video_url = video["video_url"].asCString();
const char* image_url = video["image_url"].asCString();
char sql[8192] = {0};
#define VIDEO_INSERT "insert tb_video values(null,'%s','%s','%s','%s',now());"
sprintf(sql,VIDEO_INSERT, name,vdesc,video_url,image_url);
return MysqlQuery(_mysql,sql);
}
bool Delete(int video_id)
{
#define VIDEO_DELETE "delete from tb_video where id=%d;"
char sql[8192] = {0};
sprintf(sql,VIDEO_DELETE,video_id);
return MysqlQuery(_mysql,sql);
}
bool Update(int video_id,const Json::Value &video)
{
#define VIDEO_UPDATE "update tb_video set name='%s',vdesc='%s' where id=%d;"
char sql[8192] = {0};
sprintf(sql,VIDEO_UPDATE,video["name"].asCString(),
video["vdesc"].asCString(),
video_id);
return MysqlQuery(_mysql,sql);
}
bool GetAll(Json::Value *video)
{
#define VIDEO_GETALL "select * from tb_video;"
_mutex.lock();
bool ret = MysqlQuery(_mysql,VIDEO_GETALL);
if(ret ==false)
{
_mutex.unlock();
return false;
}
MYSQL_RES * res = mysql_store_result(_mysql);
_mutex.unlock();
if(res ==NULL)
{
std::cout<<"store result failed!\n";
return false;
}
int num = mysql_num_rows(res);
for(int i = 0;i<num;++i)
{
MYSQL_ROW row = mysql_fetch_row(res);
Json::Value val;
val["id"] = std::stoi(row[0]);
val["name"] = row[1];
val["vdesc"] = row[2];
val["video_url"] = row[3];
val["image_url"] = row[4];
val["ctime"] = row[5];
video->append(val);
}
mysql_free_result(res);
return true;
}
bool GetOne(int video_id,Json::Value *video)
{
#define VIDEO_GETONE "select * from tb_video where id=%d;"
char sql_str[4096] = {0};
sprintf(sql_str,VIDEO_GETONE,video_id);
_mutex.lock();
bool ret = MysqlQuery(_mysql,sql_str);
if(ret == false)
{
_mutex.unlock();
return false;
}
MYSQL_RES *res = mysql_store_result(_mysql);
_mutex.unlock();
if(res == NULL)
{
std::cout<<mysql_error(_mysql)<<std::endl;
return false;
}
int num_row = mysql_num_rows(res);
if(num_row != 1)
{
std::cout<<"getone result error\n";
mysql_free_result(res);
return false;
}
MYSQL_ROW row = mysql_fetch_row(res);
(*video)["id"] = video_id;
(*video)["name"] = row[1];
(*video)["vdesc"] = row[2];
(*video)["video_url"] = row[3];
(*video)["image_url"] = row[4];
(*video)["ctime"] = row[5];
mysql_free_result(res);
return true;
}
};
}
前端界面模块
实现前端界面能够与用户进行交互
1.完成前端html界面的编写
html+css+js html:标签化语言,实现浏览器对于最粗糙的界面的渲染; css:层叠样式语言,实现对html进行样式美化; js:javascript脚本语言,实现让界面动态渲染,本次我们使用vue.js进行前端页面的渲染,在使用vue.js前需要本地安装或者远程请求服务。
本次项目的界面并非从零开始编写,在网上找的模板中做些修改即可,在把前端界面初步完成之后,需要使用ajax进行交互
ajax : 就像是http客户端,相当于当前界面分离的一个客户端与服务器进行数据交互,说白了ajax的作用就是,从后台获取到数据。在本次项目中,我们使用jquery ajax,使用前和vue.js一样需要本地安装或者远程请求服务。
前端界面: 负责展示当前服务器上的所有视频
单个视频播放界面: 视频播放界面需要指定到底要播哪个视频,所以需要回调函数,会用到字符串替换boost库,使用库前先安装。yum -y install boost boost_system
业务处理模块
接收前端请求进行业务处理最终响应
1.http服务器的搭建:
实现与前端的网络通信——接受客户端请求,使用httplib库完成http服务器的搭建。why不独立实现http,使用库项目难度降低,提高开发速度,用库比自己实现更为稳定。httplib可以帮助我们用更剪短的代码来搭建http服务器,用户只需要根据什么样的服务去做相应的处理就ok,从而不需要放心思至服务器的搭建而是更关注具体的业务。
httplib库: 组成: Server类: 服务端类; 用于搭建服务器,实现网络通信,解析http请求,组织http响应; Server类中就一张map表。当我们实现一个服务端时,就会在里面填充信息,请求与处理函数的映射表。
Request结构体: 将http请求数据解析后就能得到这个类的对象,包含了一次http请求中的所有信息;
Response类: 响应信息类,通常其中的数据需要用户自己添加。
#include "httplib.h"
using namespace httplib;
void helloworld(const Request &req, Response &rsp)
{
rsp.body = "<html><body><h1>Hello</h1></body></html>";
rsp.status = 200;
rsp.set_header("Content-Type", "text/html");
}
int main()
{
httplib::Server srv;
srv.set_base_dir("./wwwroot");
srv.Get("/hello",helloworld);
srv.listen("0.0.0.0",9000);
return 0;
}
正则表达式: 用来检索和替换符合文本规则的文本
2.请求与响应的网络通信接口设计
1.静态页面请求(首页,播放)
①GET/index.html HTTP/1.1(首页) 响应: HTTP/1.1 200 OK …(正文index.html文件数据)
②GET/video.html?id=1 响应: HTTP/1.1 200 OK …(正文video.html文件数据)
2.动态数据请求
视频数据信息的增删改查 多个视频对象的序列化设计——采用restful风格网络接口设计 1. 基于http,正文数据使用xml或者json格式进行序列化,我们采用json格式序列化;json是一种轻量化的数据交换格式,采用完全独立于编程语言的文本格式来存储和表示数据。 Json数值对象:数组、数字、字符串; eg:表示多个学生信息[{name:“zhangsan”,age:18,score:[77,88,99],marry:false},{name:“zhangsan”,age:18,score:[77,88,99],marry:false}]
2. restful风格里面定义了四种操作类型:新增(POST)、获取(GET)、修改(PUT)、删除(DELETE)。
①新增视频信息: 请求: POST /video HTTP/1.1 头部… 正文{name:“变形金刚”…} 响应: <1>HTTP/1.1 200 OK 头部… 无正文 <2>HTTP/1.1 500 SEVER ERROR … {result:false,reason:“mysql err”} (不适宜json格式,因为视频数据大,存在风险,使用http默认的文件上传操作html操作) 原生的文件上传,正文中分为多个表单数据域,每个域表示的是不同的提交的表单项(视频文件数据,封面图片数据,视频名称,视频描述)收到请求进行解析。 1.将视频文件数据,以及图片数据存储到对应文件中; 2.将视频路径,图片路径,视频名称,描述存储到数据库。
上传的视频文件重名如何处理?
当前做法:直接覆盖式写入 预想做法:每个用户上传的文件名都以一种独一无二的形式命名(时间戳+用户名+某种算法)。
上传的文件冗余重复(名字不同,数据实际相同)
当前做法:不作处理; 预想做法:计算每个文件的md5值存放到视频信息数据库中,每个上传的视频文件都要计算md5,然后到数据库中查找有没有相同md5的文件,如果有,则直接将url路径拿过来就行,不用存放冗余文件数据。
MD5: 是一种信息摘要算法,常用于文件数据的唯一标识,针对一个文件的数据进行大量用算得到一个md5值;文件内容一有差别得到的MD5值大不相同。Linux中MD5sum命令就是计算文件的MD5值。
②删除视频信息: 请求: DELETE /video?id=1 HTTP/1.1 … 无正文 响应: HTTP/1.1 200 OK … 正确响应则无正文
③修改视频信息: 请求: PUT /video/1(或者/video?id=1) HTTP/1.1 … {name:"", desc:"", …} 响应: HTTP/1.1 200 OK …
④获取视频信息: 获取所有: 请求: GET /video HTTP/1.1 … 无正文 响应: HTTP/1.1 200 OK … [{视频1信息},{视频2信息}…]
获取单个视频信息: 请求: GET /video/1 HTTP/1.1 … 响应: HTTP/1.1 200 OK … {视频信息}
http协议实现 http服务器:实质是tcp服务器,上层使用http协议约定数据格式。
协议格式: 首行: ①请求行:请求方法(GET/HEAD/POST/PUT…),URL(统一资源定位符http://user:pass@ip:port/path?key=val#ch),协议版本(0.9/1.0/1.1/2.0) ②协议行:协议版本,响应状态码,状态码描述;1××协议切换/2××正确处理/3××重定向/4××客户端错误/5××服务端错误
头部: 键值对组成的头部字段 Content-Type:正文类型 Content-Length:正文长度,解决http拈包问题 Connection:控制长短连接 Location:重定向新链接 Cookie、Set-Cookie:维护http通信状态–保存在客户端持续传输维护状态 session:保存在服务端,通过cookie传递sessionid,包含客户端隐私信息和状态信息
空行: \r\n:间隔头部与正文,标识头部结束位置
正文: 提交响应的数据
在基本完成模块搭建之后,使用postman模拟客户端对服务端进行请求来交互。
#include <iostream>
#include <mysql/mysql.h>
#include <jsoncpp/json/json.h>
#include <mutex>
#include <fstream>
namespace vod_system
{
#define MYSQL_HOST "127.0.0.1"
#define MYSQL_USER "root"
#define MYSQL_PASS "ljl12138"
#define MYSQL_NAME "vod_system"
static MYSQL *MysqlInit()
{
MYSQL *mysql = mysql_init(NULL);
if(mysql == NULL)
{
std::cout<<"mysql init failed!\n";
return NULL;
}
if(mysql_real_connect(mysql,MYSQL_HOST,MYSQL_USER,
MYSQL_PASS,MYSQL_NAME,0,NULL,0)==NULL)
{
std::cout<<mysql_error(mysql)<<std::endl;
mysql_close(mysql);
return NULL;
}
if(mysql_set_character_set(mysql,"utf8")!=0)
{
std::cout<<mysql_error(mysql)<<std::endl;
mysql_close(mysql);
return NULL;
}
return mysql;
}
static void MysqlRelease(MYSQL *mysql)
{
if(mysql != NULL)
{
mysql_close(mysql);
}
return;
}
static bool MysqlQuery(MYSQL *mysql, const std::string sql)
{
int ret = mysql_query(mysql,sql.c_str());
if(ret != 0)
{
std::cout<<sql<<std::endl;
std::cout<<mysql_error(mysql)<<std::endl;
return false;
}
return true;
}
class TableVod
{
private:
MYSQL *_mysql;
std::mutex _mutex;
public:
TableVod()
{
_mysql = MysqlInit();
if(_mysql == NULL)
{
exit(0);
}
}
~TableVod()
{
MysqlRelease(_mysql);
}
bool Insert(const Json::Value &video)
{
const char* name = video["name"].asCString();
const char* vdesc = video["vdesc"].asCString();
const char *video_url = video["video_url"].asCString();
const char* image_url = video["image_url"].asCString();
char sql[8192] = {0};
#define VIDEO_INSERT "insert tb_video values(null,'%s','%s','%s','%s',now());"
sprintf(sql,VIDEO_INSERT, name,vdesc,video_url,image_url);
return MysqlQuery(_mysql,sql);
}
bool Delete(int video_id)
{
#define VIDEO_DELETE "delete from tb_video where id=%d;"
char sql[8192] = {0};
sprintf(sql,VIDEO_DELETE,video_id);
return MysqlQuery(_mysql,sql);
}
bool Update(int video_id,const Json::Value &video)
{
#define VIDEO_UPDATE "update tb_video set name='%s',vdesc='%s' where id=%d;"
char sql[8192] = {0};
sprintf(sql,VIDEO_UPDATE,video["name"].asCString(),
video["vdesc"].asCString(),
video_id);
return MysqlQuery(_mysql,sql);
}
bool GetAll(Json::Value *video)
{
#define VIDEO_GETALL "select * from tb_video;"
_mutex.lock();
bool ret = MysqlQuery(_mysql,VIDEO_GETALL);
if(ret ==false)
{
_mutex.unlock();
return false;
}
MYSQL_RES * res = mysql_store_result(_mysql);
_mutex.unlock();
if(res ==NULL)
{
std::cout<<"store result failed!\n";
return false;
}
int num = mysql_num_rows(res);
for(int i = 0;i<num;++i)
{
MYSQL_ROW row = mysql_fetch_row(res);
Json::Value val;
val["id"] = std::stoi(row[0]);
val["name"] = row[1];
val["vdesc"] = row[2];
val["video_url"] = row[3];
val["image_url"] = row[4];
val["ctime"] = row[5];
video->append(val);
}
mysql_free_result(res);
return true;
}
bool GetOne(int video_id,Json::Value *video)
{
#define VIDEO_GETONE "select * from tb_video where id=%d;"
char sql_str[4096] = {0};
sprintf(sql_str,VIDEO_GETONE,video_id);
_mutex.lock();
bool ret = MysqlQuery(_mysql,sql_str);
if(ret == false)
{
_mutex.unlock();
return false;
}
MYSQL_RES *res = mysql_store_result(_mysql);
_mutex.unlock();
if(res == NULL)
{
std::cout<<mysql_error(_mysql)<<std::endl;
return false;
}
int num_row = mysql_num_rows(res);
if(num_row != 1)
{
std::cout<<"getone result error\n";
mysql_free_result(res);
return false;
}
MYSQL_ROW row = mysql_fetch_row(res);
(*video)["id"] = video_id;
(*video)["name"] = row[1];
(*video)["vdesc"] = row[2];
(*video)["video_url"] = row[3];
(*video)["image_url"] = row[4];
(*video)["ctime"] = row[5];
mysql_free_result(res);
return true;
}
};
class Util
{
public:
static bool WriteFile(const std::string &name,const std::string &content)
{
std::ofstream of;
of.open(name,std::ios::binary);
if(!of.is_open())
{
std::cout<<"open file failed!\n";
return false;
}
of.write(content.c_str(),content.size());
if(!of.good())
{
std::cout<<"write file failed!\n";
return false;
}
of.close();
return true;
}
};
}
主函数
#include <boost/algorithm/string.hpp>
#include "db.hpp"
#include "httplib.h"
#include <fstream>
#define WWWROOT "./wwwroot"
using namespace httplib;
vod_system::TableVod *tb_video;
void VideoDelete(const Request &req, Response &rsp)
{
int video_id= std::stoi(req.matches[1]);
Json::Value json_rsp;
Json::FastWriter writer;
Json::Value video;
bool ret = tb_video->GetOne(video_id,&video);
if(ret == false)
{
std::cout<< "mysql get video info failed!\n";
rsp.status = 500;
json_rsp["result"] = false;
json_rsp["reason"] = "mysql get video info failed!";
rsp.body = writer.write(json_rsp);
rsp.set_header("Content-Type","application/json");
return;
}
std::string vpath = WWWROOT + video["video_url"].asString();
std::string ipath = WWWROOT + video["image_url"].asString();
unlink(vpath.c_str());
unlink(ipath.c_str());
ret = tb_video->Delete(video_id);
if(ret == false)
{
rsp.status = 500;
std::cout<<"mysql delete video failed!\n";
return;
}
return;
}
void VideoUpdate(const Request &req, Response &rsp)
{
int video_id= std::stoi(req.matches[1]);
Json::Value video;
Json::Reader reader;
bool ret = reader.parse(req.body ,video);
if(ret ==false)
{
std::cout<<"update video : parse video json failed!\n";
rsp.status = 400;
return;
}
ret = tb_video->Update(video_id, video);
if(ret == false)
{
std::cout<<"update video:mysql update failed!\n";
rsp.status=5000;
return;
}
return;
}
void VideoGetAll(const Request &req, Response &rsp)
{
Json::Value videos;
Json::FastWriter writer;
bool ret = tb_video->GetAll(&videos);
if(ret == false)
{
std::cout<<"getall video:mysql operation failed!\n";
rsp.status = 500;
return;
}
rsp.body = writer.write(videos);
rsp.set_header("Content-Type", "application/json");
}
void VideoGetOne(const Request &req, Response &rsp)
{
int video_id= std::stoi(req.matches[1]);
Json::Value video;
Json::FastWriter writer;
bool ret = tb_video->GetOne(video_id,&video);
if(ret == false)
{
std::cout<<"getone video:mysql operation failed!\n";
rsp.status = 500;
return;
}
rsp.body = writer.write(video);
rsp.set_header("Content-Type", "application/json");
}
#define VIDEO_PATH "/video/"
#define IMAGE_PATH "/image/"
void VideoUpload(const Request &req, Response &rsp)
{
auto ret = req.has_file("video_name");
if(ret == false)
{
std::cout<<"have no video name!\n";
rsp.status = 400;
return;
}
const auto & file = req.get_file_value("video_name");
ret = req.has_file("video_desc");
if(ret == false)
{
std::cout<<"have no video desc!\n";
rsp.status = 400;
return;
}
const auto& file1 = req.get_file_value("video_desc");
ret = req.has_file("video_file");
if(ret == false)
{
std::cout<<"have no video file!\n";
rsp.status = 400;
return;
}
const auto& file2 = req.get_file_value("video_file");
ret = req.has_file("image_file");
if(ret == false)
{
std::cout<<"have no image file!\n";
rsp.status = 400;
return;
}
const auto& file3 = req.get_file_value("image_file");
const std::string &videoname = file.content;
const std::string &videodesc = file1.content;
const std::string& videofile = file2.filename;
const std::string& videocont = file2.content;
const std::string &imagefile = file3.filename;
const std::string &imagecont = file3.content;
std::string vurl = VIDEO_PATH + file2.filename;
std::string iurl = IMAGE_PATH + file3.filename;
std::string wwwroot = WWWROOT;
vod_system::Util::WriteFile(wwwroot + vurl,file2.content);
vod_system::Util::WriteFile(wwwroot + iurl,file3.content);
Json::Value video;
video["name"] = videoname;
video["vdesc"] = videodesc;
video["video_url"] = vurl;
video["image_url"] = iurl;
ret = tb_video->Insert(video);
if(ret == false)
{
rsp.status = 500;
std::cout<<"insert video: mysql operation failed!\n";
return;
}
rsp.set_redirect("/");
return;
}
bool ReadFile(const std::string &name, std::string *body)
{
std::ifstream ifile;
ifile.open(name, std::ios::binary);
if(!ifile.is_open())
{
printf("open file failed111:%s\n",name.c_str());
ifile.close();
return false;
}
ifile.seekg(0,std::ios::end);
uint64_t length = ifile.tellg();
ifile.seekg(0,std::ios::beg);
body->resize(length);
ifile.read(&(*body)[0],length);
if(ifile.good() == false)
{
printf("read file failed:%s\n", name.c_str());
ifile.close();
return false;
}
ifile.close();
return true;
}
void VideoPlay(const Request &req, Response &rsp)
{
Json::Value video;
int video_id = std::stoi(req.matches[1]);
bool ret = tb_video->GetOne(video_id,&video);
if(ret == false)
{
std::cout<<"getone video:mysql operation failed!\n";
rsp.status = 500;
return;
}
std::string newstr = video["video_url"].asString();
std::string oldstr = "{{video_url}}";
std::string play_html = "./wwwroot/single-video.html";
ReadFile(play_html,&rsp.body);
boost::algorithm::replace_all(rsp.body,oldstr,newstr);
rsp.set_header("Content-Type", "text/html");
return;
}
int main()
{
tb_video = new vod_system::TableVod();
Server srv;
srv.set_base_dir("./wwwroot");
srv.Delete(R"(/video/(\d+))",VideoDelete);
srv.Put(R"(/video/(\d+))",VideoUpdate);
srv.Get(R"(/video)",VideoGetAll);
srv.Get(R"(/video(\d+))",VideoGetOne);
srv.Post(R"(/video)",VideoUpload);
srv.Get(R"(/play/(\d+))",VideoPlay);
srv.listen("0.0.0.0",9000);
return 0;
}
总结
项目源码
|