关于全栈项目【臻美短视频】总结
登录注册页
视频展示页
上传拍摄视频页
以上是臻美短视频的基本页面。
这个项目的有几大难点:
一、登录注册功能的实现
二、视频数据的实时获取以及上滑切换视频
三、上传视频以及录制视频
那么我们一步一步分析
一、登录注册功能的实现
这里后台使用的是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>
作者:Vam的金豆之路
主要领域:前端开发
我的微信:maomin9761
微信公众号:前端历劫之路