关于全栈项目【臻美短视频】总结
登录注册页
视频展示页
上传拍摄视频页
以上是臻美短视频的基本页面。
这个项目的有几大难点:
一、登录注册功能的实现
二、视频数据的实时获取以及上滑切换视频
三、上传视频以及录制视频
那么我们一步一步分析
一、登录注册功能的实现
这里后台使用的是nodejs,调用相应的端口就可以存入数据库。
var express = require('express')
var multer = require('multer')
var jwt = require('jsonwebtoken');
var mysql = require('mysql');
var bodyParser = require('body-parser')
// 如果使用POST方法,就必须导入bodyParser,body-parser请求体解析模块,是express的中间件用于接受请求体中的数据,并解析为对象,解析之后的对象会将作为body属性添加给rep对象
var fs = require('fs');
var join = require('path').join;
var web = express();
var secretkey = 'secretkey';
var connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: '',
port: '3306',
database: 'sv'
});
connection.connect();
web.use(express.static('public'))
// 设置服务器静态文件夹,里面的文件都是呈现给人们看的网页
web.use(bodyParser.json());
web.use(bodyParser.urlencoded({
extended: true
}));
web.all("*", function (req, res, next) {
res.header('Access-Control-Allow-Origin', req.headers.origin || '*');
res.header('Access-Control-Allow-Headers', 'Content-Type,Content-Length, Authorization,\'Origin\',Accept,X-Requested-With');
res.header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
res.header('Access-Control-Allow-Credentials', true);
res.header('X-Powered-By', ' 3.2.1');
res.header('Content-Type', 'application/json;charset=utf-8');
if (req.method.toLowerCase() == 'options')
res.send(200); //让options尝试请求快速结束
else
next();
})
//用户登录
web.post('/user/login', (req, res) => {
var name = req.body.username;
var passwd = req.body.password;
var userStr = `select username,password,token from user where username="${ name}" and password="${ passwd}"`;
connection.query(userStr, function (err, result) {
if (err) {
throw err;
} else {
res.json({
message: result,
})
}
})
})
//符合
web.post('/user/accord', (req, res) => {
var token2 = req.body.token1;
var userStr = `select username,token from user where token="${ token2}"`;
connection.query(userStr, function (err, result) {
if (err) {
throw err;
} else {
res.json({
message: result,
})
}
})
})
//用户注册
web.post('/user/register', (req, res) => {
var name = req.body.username;
var passwd = req.body.password;
var token1 = jwt.sign({
username: name
}, secretkey, {
expiresIn: 60 * 8
});
var json = { };
var userStr = `select * from user where username="${ name}"`;
connection.query(userStr, function (err, result) {
if (err) throw err;
if (result.length > 0) {
json.message = '用户已经存在';
json.resultCode = 1;
} else {
json.message = '注册成功';
json.token = token1;
json.resultCode = 200;
var insertStr = `insert into user (username, password,token) values ("${ name}", "${ passwd}","${ token1}")`;
console.log(insertStr)
connection.query(insertStr, function (err, res) {
if (err) throw err;
})
}
res.send(JSON.stringify(json))
})
})
var fullName = '';
var pa="";
var y1="";
var i=0;
var userq=''
web.post('/username', function (req, res) {
// res.send('')
userq = req.body.name;
console.log(userq)
})
var headerConfig = multer.diskStorage({
// destination目的地
destination: 'public/video',
filename: function (req, file, cb) {
var fileFormat = (file.originalname).split(".");
cb(null, userq + '-' + Date.now() + "." + fileFormat[fileFormat.length - 1]);
}
})
var upload = multer({
storage: headerConfig
})
function getJsonFiles(jsonPath) {
let jsonFiles = [];
function findJsonFile(path) {
let files = fs.readdirSync(path);
files.forEach(function (item, index) {
let fPath = join(path, item);
let stat = fs.statSync(fPath);
if (stat.isDirectory() === true) {
findJsonFile(fPath);
}
if (stat.isFile() === true) {
let fail = fPath.slice(7);
jsonFiles.push('https://www.xxx.cn/xxx/' + fail);
}
});
}
findJsonFile(jsonPath);
// console.log(jsonFiles);
pa = jsonFiles;
}
web.post('/upload',upload.single('video'), function (req, res) {
// res.send('')
console.log('上传成功')
})
web.get('/video', function (req, res) {
getJsonFiles("./public/video");
res.send(pa);
})
web.listen('7500', function () {
console.log('服务器开启')
})
前台使用的是Vue,UI框架Vant。前台比较简单,这里不多过叙述。
<template>
<div>
<div class="logo"><img src="../assets/video.png" alt=""></div>
<van-cell-group class="int">
<van-field v-model="username" clearable label="用户名" placeholder="请输入用户名" maxlength="6" clickable />
<van-field v-model="password" type="password" label="密码" maxlength="6" placeholder="请输入密码" clickable />
</van-cell-group>
<div class="foot">
<van-button type="primary" color="#00CED1" class="login" @click="log" >登录</van-button>
<p class="reg" @click="reg">注册</p>
</div>
</div>
</template>
<script>import md5 from 'js-md5' const delay = (function () { let timer = 0 return function (callback, ms) { clearTimeout(timer) timer = setTimeout(callback, ms) } })() export default { name: 'login', data () { return { username: '', password: '', sse: '' } }, methods: { reg () { if (this.username.length !== 0 && this.password.length !== 0) { delay(() => { let postData = { username: this.username, password: md5(this.password) } this.$axios.post('https://xxx/xxxx/user/register', postData) .then((response) => { // success console.log(response.data) if (response.data.resultCode === 200) { this.$notify({ message: response.data.message, duration: 1000, background: '#07C160' }) this.username = '' this.password = '' } else if (response.data.resultCode === 1) { this.$notify({ message: response.data.message, duration: 1000, background: '#FFA500' }) } }) .catch((error) => { // error console.log(error) }) }, 500) } else { this.$notify({ message: '注册失败!', duration: 1000, background: '#FF0000' }) } }, log () { delay(() => { let postData = { username: this.username, password: md5(this.password) } this.$axios.post('https://xxx/xxx/user/login', postData) .then((response) => { // success console.log(response.data.message) if (response.data.message.length === 0) { // ('登录失败') this.$notify({ message: '登录失败!', duration: 1000, background: '#FF0000' }) } else { localStorage.setItem('svuser', response.data.message[0].token) localStorage.setItem('svdata', JSON.stringify(response.data.message[0])) this.$router.push({ name: 'index' }) this.$notify({ message: '登录成功!', duration: 1000, background: '#07C160' }) } }) .catch((error) => { // error console.log(error) }) }, 500) } } } </script>
二、视频数据的实时获取以及上滑切换视频
视频获取直接调用接口就可以了
<template>
<div class="index">
<div class="close" @click="close">
<div>
<van-icon name="cross" color="#00CED1"/>
</div>
</div>
<van-swipe style="height: 100vh;" vertical :show-indicators="false" @change="onChange" touchable>
<van-swipe-item v-for="(item,index) in list" :key="index">
<div class="main" v-if="playIndex==index">
<video loop :src="item" preload autoplay="autoplay" controls="controls"></video>
<div class="foot">
<p class="name">@ {
{ item | capitalize }}</p>
</div>
</div>
</van-swipe-item>
</van-swipe>
<div class="add">
<div @click="b1()">
<van-button icon="plus" color="#00CED1" />
</div>
</div>
</div>
</template>
<script> export default { name: 'index', data () { return { current: 0, list: '', playIndex: 0 } }, methods: { close () { this.$notify({ message: '退出成功!', duration: 1000, background: '#07C160' }) setTimeout(() => { localStorage.clear() window.location.reload() }, 1000) }, onChange (index) { this.current = index this.playIndex = index console.log(index) }, b1 () { const data1 = JSON.parse(localStorage.getItem('svdata')) this.$router.push({ name: 'upload', params: { name: data1.username } }) } }, filters: { capitalize: function (value) { // console.log(value.slice(39)) let a = value.slice(39) return a.split('-')[0] } }, mounted () { // location.reload() // document.querySelector('video').playbackRate = 0.75 const data1 = JSON.parse(localStorage.getItem('svdata')) if (data1.token === localStorage.getItem('svuser')) { // this.name = data1.username this.$axios.get('https://xxx/xxx/video/') .then((response) => { // success console.log(response.data) this.list = response.data }) .catch((error) => { // error console.log(error) }) } } } </script>
三、上传视频以及录制视频
这里使用的是node的multer模块
var fullName = '';
var pa="";
var y1="";
var i=0;
var userq=''
web.post('/username', function (req, res) {
// res.send('')
userq = req.body.name;
console.log(userq)
})
// 思路
// 上传内容并储存——1.设置存储的地方——2.设置存储时的名字{1.获取原来名字的后缀,2.再重新命名}
var headerConfig = multer.diskStorage({
// destination目的地
destination: 'public/video',
// fliename 文件名 后面跟函数,函数有三个参数
// file为当前上传的文件
filename: function (req, file, cb) {
var fileFormat = (file.originalname).split(".");
cb(null, userq + '-' + Date.now() + "." + fileFormat[fileFormat.length - 1]);
}
})
// 设置使用当前的配置信息
// 上传完照片后要使用的配置信息
var upload = multer({
storage: headerConfig
})
function getJsonFiles(jsonPath) {
let jsonFiles = [];
function findJsonFile(path) {
let files = fs.readdirSync(path);
files.forEach(function (item, index) {
let fPath = join(path, item);
let stat = fs.statSync(fPath);
if (stat.isDirectory() === true) {
findJsonFile(fPath);
}
if (stat.isFile() === true) {
let fail = fPath.slice(7);
jsonFiles.push('https://xxx/xxx/' + fail);
}
});
}
findJsonFile(jsonPath);
// console.log(jsonFiles);
pa = jsonFiles;
}
// single 上传单个文件; photo 为前端上传文件的input标签的name值
// upload.single('video')每次上传单个文件的配置信息
web.post('/upload',upload.single('video'), function (req, res) {
// res.send('')
console.log('上传成功')
})
web.get('/video', function (req, res) {
getJsonFiles("./public/video");
res.send(pa);
})
这里前台直接使用的是Vant框架中的文件上传组件,但是你需要注意的是需要将let data = new FormData()
data.append('video', file.file)
然后再传到后台去
<template>
<div class="upload">
<div class="back" @click="onClickLeft">
<van-icon name="arrow-left" color="#00CED1" size="26" />
</div>
<div class="box">
<van-uploader :after-read="afterRead" :max-count="1" :max-size="10485760" v-model="fileList" accept="video/*" @oversize='chance()' />
<p>请上传不大于10M视频</p>
</div>
</div>
</template>
<script> export default { name: 'upload', data () { return { fileList: [], e: 'video' } }, methods: { chance () { this.$notify({ message: '文件大小过大,请上传小于10M视频', duration: 1000, background: '#FFA500' }) }, onClickLeft () { history.back() }, afterRead (file) { // console.log(file.content)// base64 // function dataURItoBlob (base64Data) { // var byteString // if (base64Data.split(',')[0].indexOf('base64') >= 0) byteString = atob(base64Data.split(',')[1]) // else byteString = unescape(base64Data.split(',')[1]) // var mimeString = base64Data.split(',')[0].split(':')[1].split(';')[0] // var ia = new Uint8Array(byteString.length) // for (var i = 0; i < byteString.length; i++) { // ia[i] = byteString.charCodeAt(i) // } // return new Blob([ia], { // type: mimeString // }) // } // console.log(dataURItoBlob(file.content)) let data = new FormData() data.append('video', file.file) // 此时可以自行将文件上传至服务器 this.$axios({ url: 'https://xxx/xxx/upload/', method: 'POST', headers: { 'Content-Type': 'multipart/form-data' }, data: data }).then((response) => { // success }) .catch((error) => { // error console.log(error) }) // console.log(file) this.$notify({ message: '发布成功', duration: 1000, background: '#07C160' }) } }, mounted () { this.$axios({ url: 'https://xxx/xxx/username/', method: 'POST', data: { name: this.$route.params.name } }).then((response) => { // success console.log(response) }) .catch((error) => { // error console.log(error) }) } } </script>
还没有评论,来说两句吧...