基于C++的视频点播系统
視頻點播系統
- 項目描述
- 概要設計
- 技術調研
- 詳細設計
- 數據管理模塊
- 1.數據存儲
- 2.封裝實現數據庫訪問類
- 1.了解mysql的c語言庫接口
- jsoncpp的基本使用:
- 3.數據管理模塊代碼
- 前端界面模塊
- 1.完成前端html界面的編寫
- 業務處理模塊
- 1.http服務器的搭建:
- 2.請求與響應的網絡通信接口設計
- 1.靜態頁面請求(首頁,播放)
- 2.動態數據請求
- 上傳的視頻文件重名如何處理?
- 上傳的文件冗余重復(名字不同,數據實際相同)
- 總結
項目描述
一個用戶可以通過瀏覽器上傳視頻,且對自己上傳的視頻進行管理,而其他用戶可以通過瀏覽器觀看視頻。
概要設計
采用不太嚴謹的MVC框架。此項目分模塊進行設計——數據管理模塊:對數據進行統一管理,外界只能通過此模塊訪問;用戶界面/前端界面模塊:實現用戶交互,提供前端界面;業務處理模塊:接收前端請求進行處理完成用戶的需求。
技術調研
socket、http、tcp、json、mysql、前端三劍客(html、css、js)
詳細設計
數據管理模塊
1.數據存儲
采用MySQL數據庫——免費,采用c/s架構,可以遠程訪問以及有統一接口,安全便于擴展。
數據庫表的設計:
視頻信息表:視頻id、視頻名稱、視頻描述、上傳時間、視頻文件路徑、封面圖路徑。
2.封裝實現數據庫訪問類
該類提供視頻信息的增刪改查(所有視頻/單個視頻);
數據庫表的訪問類的實現
1.了解mysql的c語言庫接口
1.定義mysql句柄
2.初始化mysql句柄
3.連接mysql服務器
4.設置客戶端字符編碼集
5.切換選擇數據庫
6.執行語句(庫,表,數據操作—sql語句的執行)增,刪,改–只要語句執行成功,就表示完成了查-需要執行語句成功后對數據進行操作
①.將查詢結果保存到本地
②.獲取保存的結果集中的數據條數和列數3.遍歷逐條取出結果集中的每一條數據4.釋放結果集
7.關閉句柄,釋放資源
8.獲取某個接口執行失敗原因的接口
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類:
響應信息類,通常其中的數據需要用戶自己添加。
正則表達式:
用來檢索和替換符合文本規則的文本
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"///video/**.mp4(數據庫中的存儲的的視頻信息)using namespace httplib;vod_system::TableVod *tb_video;//why全局變量,因為httplib庫是基于多線程void VideoDelete(const Request &req, Response &rsp) {//req.path = /video/1 req.matches存放正則表達式匹配到的內容//1.獲取視頻idint video_id= std::stoi(req.matches[1]);//2.從數據庫中獲取到對應視頻信息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();//3.刪除視頻文件,封面圖文件//unlink刪除指定名字的文件unlink(vpath.c_str());unlink(ipath.c_str());//4.刪除數據庫中的數據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) {//1.獲取視頻idint video_id= std::stoi(req.matches[1]);Json::Value video;Json::Reader reader;bool ret = reader.parse(req.body ,video);//提交上來的需要修改的json序列化后的字符串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;//***.mp4const std::string& videocont = file2.content;//視頻文件數據const std::string &imagefile = file3.filename;//***。jpgconst std::string &imagecont = file3.content;//封面文件數據///組織路徑std::string vurl = VIDEO_PATH + file2.filename;std::string iurl = IMAGE_PATH + file3.filename;std::string wwwroot = WWWROOT;//因為WWWROOT是const char *沒有重載+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);//正則表達式,\d表示匹配一個數字字符//+表示匹配字符一次或多次 //R"(string)"去除括號中字符串中每個字符的特殊含義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; }/*//插入測試 void test() {vod_system::TableVod tb_vod;Json::Value val;val["name"] = "電鋸驚魂2";val["vdesc"] = "這是個比較凈損的電影";val["video_url"] = "/video/saw2.mp4";val["image_url"] = "/video/saw2.jpg";tb_vod.Insert(val);return; }*//* void test()//查詢測試 {vod_system::TableVod tb_vod;Json::Value val;tb_vod.GetOne(3,&val);Json::StyledWriter writer;std::cout<<writer.write(val)<<std::endl;return;}*//* void test()//刪除測試 {vod_system::TableVod tb_vod;Json::Value val;val["name"] = "電鋸驚魂";val["vdesc"] = "這是個比較凈損的電影";val["video_url"] = "/video/saw.mp4";val["image_url"] = "/video/saw.jpg";tb_vod.Delete(2);return; }*//* void test()//修改測試 {vod_system::TableVod tb_vod;Json::Value val;val["name"] = "電鋸驚魂";val["vdesc"] = "這是個很血腥的電影";val["video_url"] = "/video/saw.mp4";val["image_url"] = "/video/saw.jpg";tb_vod.Update(2,val);return; }*//*void test1() {vod_system::TableVod tb_vod;Json::Value val;val["name"] = "速度與激情9";val["vdesc"] = "這是個非常刺激的電影";val["video_url"] = "/video/speed.mp4";val["image_url"] = "/video/speed.jpg";tb_vod.Insert(val);return; }*/ /* int main() {//局部功能測試test();return 0; }*/總結
項目源碼
總結
以上是生活随笔為你收集整理的基于C++的视频点播系统的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: AI时代下的围棋
- 下一篇: s3c2440移植MQTT