目录
一、 引言 1
1.1弹幕视频介绍 1
1.2文档说明 1
1.3编写目的 1
1.4文档范围 1
二、 程序实现功能描述 2
2.1用户登录注册(包含验证码校验) 2
2.2视频搜索、用户搜索 2
2.3视频详情页 2
2.4用户修改账户信息 3
2.5用户上传视频 4
2.6用户编辑已经上传过视频的信息 4
2.7用户下载自己已经上传过的视频 5
2.8用户查看视频、UP主信息 5
2.9用户权限控制 5
三、 系统总体功能设计 6
3.1未登录用户功能设计 6
3.2已登录用户功能设计 6
四、 模块实现 7
4.1登录与注册模块 7
4.2视频搜索、UP主搜索模块 8
4.3用户账户管理模块 10
4.4视频编辑、上传、下载模块 12
4.5视频详情模块 15
五、 网站总结 17
5.1弹幕视频系统 17
5.2头像上传系统 17
5.3视频上传系统 17
5.4视频下载等 17
二、程序实现功能描述
2.1用户登录注册(包含验证码校验)
2.1.1登录
已经在本站注册过的用户,可以使用用户名和密码登录,与此同时,用户需要填写一个随机生成的验证码,只有用户名密码符合要求,并且输入的验证码正确,才可以成功登陆
2.1.2注册
尚未注册过的用户,可以通过注册页面来注册一个账户,用户需要输入账户名、密码以及确认密码,以及个人简介等(个人简介可以为空),如果这个账户已经被注册过,则需要重新输入,如果尚未注册,且密码符合要求,则成功注册。
2.2视频搜索、用户搜索
2.2.1视频搜索
无论用户是否登录,都可以对视频进行搜索,并指定搜索到的视频按照一定的顺序排序。搜索到的视频可以看到封面、标题、类型、简介,以及点击量、收藏量、弹幕量、上传时间以及UP主[[] UP主:上传视频的人],点击相应的视频封面,用户可以进入视频详情页面
2.2.2用户搜索
用户可以搜索全站内的UP主,搜索到的UP主可以按照投稿量(上传视频的数量)、粉丝量(关注此用户的用户数量)和默认排序进行排序显示,每个UP主如果上传了视频,会显示出最多3个视频,点击可以进入相应的视频页面。
2.2.3模糊查询
无论是用户搜索还是视频搜索,都提供模糊查询功能。即在输入框输入相应的内容,后台会匹配包含该字段的视频或者UP主,并显示在主页面上。视频标题或者UP主的名字如果包含该字段会被标红显示。
2.3视频详情页
2.3.1视频观看
用户可以点击视频播放器观看视频,播放器提供发送弹幕、调节音量、屏蔽弹幕、全屏显示等功能。全屏显示调用了screenfull.js插件,该插件可以方便地实现全屏化的功能。
2.3.2发送弹幕
用户在已经登录的状态,可以发送弹幕,发送的弹幕可以设置弹幕的样式,同时发送的时候可以实时显示,同一时刻支持多条不同样式的弹幕同时显示。使用了danmu.js插件并对插件进行定制化修改,使得在用户在进入视频详情页面并打开视频的时候会增加视频的浏览量,在输入弹幕的时候可以将弹幕发送到后台并存储进入服务器,同时在视频加载的时候可以获取该视频的所有弹幕。
2.3.3收藏视频
用户在已登录的状态,可以通过视频下方的收藏按钮,进行收藏或者取消收藏的操作,并有相应的提示
2.3.4评论视频
用户在已登录的状态,可以在下方评论栏对视频进行评论,评论的内容可以实时无刷新地显示在网页上,显示的内容包括评论时间、评论者、评论者头像、该评论获得赞的数量等等。如果当前视频一条评论也没有,会有无评论的显示。
2.3.5关注视频上传者
在视频的右上角,有当前视频上传者的信息,包括该UP主头像、账户名、投稿量、关注的人数量、粉丝的数量,同时具备一个关注按钮。用户可以通过点击关注按钮对该用户进行关注和取消关注,并会有实时显示。
2.3.6推荐视频上传者更多视频
如果该UP主除了当前正在播放的视频之外还有其他上传的视频,可以最多同时显示5个视频推荐,用户可以看到该视频的封面和标题,点击相应的封面可以进入对应的视频详情信息。
2.4用户修改账户信息
2.4.1修改密码
用户可以通过点击修改密码按钮对自己的密码进行修改,用户需要输入当前的密码、新密码和确认新的密码,如果当前密码正确并且新的密码符合要求,则用户修改密码成功,同时跳转到登录页面,要求用户重新登录。
2.4.2修改简介
用户可以通过点击修改简介按钮对自己的简介进行修改,点击按钮之后简介的输入框变为可用,此时用户可以对简介进行修改,如果再次点击该按钮,会异步刷新提交数据库
2.4.3修改头像
用户可以修改自己的头像,通过选择相应的符合格式的图片文件之后,可以弹出一个裁剪视频的模态框,用户可以实时对画面的指定部分进行截取并实时显示出自己截取过后头像的效果,确认截取并点击上传之后,可以完成对头像的修改。这部分用到Canvas的图像截取技术,并且应用了图片区域选择插件jquery-imagearea-select.js,本文转载自http://www.biyezuopin.vip/onews.asp?id=15016选择过后,图片的内容通过base64编码上传到后台,后台通过解析这个格式的文件并保存为图像到服务器同时更新数据库。
2.5用户上传视频
2.5.1传统form表单上传
用户可以通过两个文件选择的input标签来选择自己所需要的封面和视频,但是这种视频的上传方式限制比较多,不仅无法实现文件的断点续传,而且在文件大小比较大的时候,会耗用大量的时间在跳转的页面上,所以这种上传的方式是不优化的,所以只是实现了一个基本的功能,而没有过多的附加功能
2.5.2新版上传
用户在新版上传界面里面,除了需要定义基本的视频信息之外,在视频上传这块有着很多优化。首先它使用了plupload.js这个插件,用户可以看到视频上传的进度,所以交互性非常好。同时设计了断点续传功能,也就是用户每上传一定的大小就会在后台写入一个临时文件,在选择文件之后,如果自己曾经上传过这个视频,那么服务器会有一个临时文件,所以在自己上传的时候就可以检测到该文件,在上传的时候可以从该断点的时候开始上传。这样,实现断点上传,已经添加的文件也可以通过删除按钮删除。同时,上传的过程中可以点击暂停上传,这样服务器所缓存的文件就会停留在当前的进度下。
package com.yida.common;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
//视频管理页面
public class MyVideoItem {
private int id;//视频的id
private int upperId;//上传者的id,也就是当前用户的id
private String videoPath;//视频地址
private String coverPath;//视频封面
private String type;//视频类型
private String title;//视频标题
private Date uploadTime;//上传时间
private int viewNum;//观看次数
private int danmuNum;//弹幕数量
private int collectNum;//收藏数量
private int commentNum;//评论数量
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getUpperId() {
return upperId;
}
public void setUpperId(int upperId) {
this.upperId = upperId;
}
public String getVideoPath() {
return videoPath;
}
public void setVideoPath(String videoPath) {
this.videoPath = videoPath;
}
public String getCoverPath() {
return coverPath;
}
public void setCoverPath(String coverPath) {
this.coverPath = coverPath;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public Date getUploadTime() {
return uploadTime;
}
public String getUploadDetailTime(){
DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return format.format(uploadTime);
}
public void setUploadTime(Date uploadTime) {
this.uploadTime = uploadTime;
}
public int getViewNum() {
return viewNum;
}
public void setViewNum(int viewNum) {
this.viewNum = viewNum;
}
public int getDanmuNum() {
return danmuNum;
}
public void setDanmuNum(int danmuNum) {
this.danmuNum = danmuNum;
}
public int getCollectNum() {
return collectNum;
}
public void setCollectNum(int collectNum) {
this.collectNum = collectNum;
}
public int getCommentNum() {
return commentNum;
}
public void setCommentNum(int commentNum) {
this.commentNum = commentNum;
}
}