关于全栈项目【臻美短视频】总结

登录注册页




























视频展示页


























上传拍摄视频页

































以上是臻美短视频的基本页面。

这个项目的有几大难点:
一、登录注册功能的实现
二、视频数据的实时获取以及上滑切换视频
三、上传视频以及录制视频

那么我们一步一步分析
一、登录注册功能的实现

这里后台使用的是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

微信公众号:前端历劫之路