这个项目的有几大难点:
一、登录注册功能的实现
二、视频数据的实时获取以及上滑切换视频
三、上传视频以及录制视频
那么我们一步一步分析
一、登录注册功能的实现
这里后台使用的是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>