文章目录
- 前言
- 回顾
- 完成任务
- 1. 客户端获取视频分类
- 2. 上传视频(投稿)
- 2.1 预上传
- 2.2 视频分片上传
- 2.3 删除已上传到临时目录的视频
- 2.4 上传图片
- 2.5 上传视频
- 总结

前言
本项目非原创,我只是个小小白,跟随 b 站脚步,找到老罗的这个项目,视频来源于:
高仿B站(单服务版) springboot项目实战 easylive
本人不分享项目源码,支持项目付费!!!
回顾
昨天完成了视频的分类管理,后台做好了分类工作,现在就可以对客户端发布视频的功能进行处理。
完成任务
1. 客户端获取视频分类
controller 层:
先前服务端已经将视频的分类保存在了 Redis 中,那么客户端获取的时候,可直接从 Redis 中获取:
客户端要获取每个分类的图标和背景图,也需要获取文件的接口,也就是服务端中获取文件的方法 getResource() 是类似的,这里直接将管理端获取的方法 copy 过来(但是,其实并没有那么简单,这里后面还会修改):
默认的背景图怎么实现的 ?
2. 上传视频(投稿)
2.1 预上传
预上传会向后端请求一个接口,后端返回一个随机字符串,也就是表示这个视频的唯一 Id;后面真正的视频上传请求(也就是每一个切片请求)都会携带这个 Id,这样就知道这个切片上传的是哪个视频的。因为可以有多个视频文件同时上传,所以每个切片要通过这个唯一 Id 找到它自己属于哪个视频。
预上传时,会携带这个文件名,以及分片数目,分片是在客户端完成的:
预上传,controller 层:
将视频文件信息存在 Redis 中,并返回生成的视频 Id:
使用一个文件上传的 Dto 类 UploadingFileDto,主要包括文件上传中需要的相关信息:
将每上传的文件分片放在临时目录 temp 下,当所有分片完全上传以后,再对 temp 中的分片进行合并,避免在文件上传过程中因为关闭页面或其他原因,使视频没有完全上传,导致正式文件夹中有许多因残余的分片。而 temp 中的文件会在给定的一个时间后进行删除。
2.2 视频分片上传
controller 层:
-
每个分片上传时,都会携带先前返回给客户端的视频上传 Id。从 Redis 中获取预上传时存入的上传文件信息,如果不存在,说明在 Redis 中已经过期了(在 Redis 的给定的过期时间内还没有上传完)。
-
SysSettingDto 类是一个与视频相关的系统配置类,包括视频大小、视频数量、评论数量、弹幕数量等:
从 Redis 中获取系统设置信息。 -
判断分片是否合理,将当前要上传的分片传到 temp 临时目录中。
-
并在 Redis 中记录上传当前视频的第几块分片,以及总的文件大小:
2.3 删除已上传到临时目录的视频
当文件成功上传到服务器后,可以点击选择删除该视频:
controller 层:
删掉 Redis 中存储的视频文件,也要删除本地磁盘临时目录 temp 中存放的视频文件。
2.4 上传图片
发布视频,会上传封面:
点击立即投稿时,会先请求 uploadImage 这个接口来上传封面图片:
controller 层:
注意
:文件的不为空使用的是 @NotNull,String 类型才可以使用 @NotEmpty。这些都是依赖于 Spring 的 @Validated 注解的,所以必须在类头上加上 @Validated 。
最后要将图片存储的相对路径返回给客户端,以便于客户端以后获取。
2.5 上传视频
前面做的都是预备工作,接下来才开始将视频上传,存储在数据库中,客户端访问的时候从数据库中获取。
注意
:新增视频和修改视频用的都是同一个接口,有视频 id 就是修改,没有 id 就是新增。
controller 层:
- 上传文件时,可以进行分P投稿,uploadFileList 是选择的所有分P的视频文件的 Json 数据。
“分P” 是什么意思 ?没有发布过 b 站视频的可能并不了解:其实它是指将一个完整的视频分为多个部分(P),并作为一个系列或合集上传到同一个视频页面中。比如,你上传一个教程视频,但这个教程过长,可以通过分P功能把它分成多个小段,每一段称为一个“P”,这样观众在观看时可以更方便地选择具体的部分。
通过 videoInfoPostService 调用 saveVideoInfo():
- 判断一系列异常情况:(1)上传的分P视频数量超过了系统设置的最大分P数量;(2)videoId 不为空,说明是修改操作,那就要判断这个视频是否存在于数据库中;对于处于转码中和待审核状态的视频,不能修改。
如果没有异常的情况,就要看此次操作是新增还是修改,修改包括删除该视频中的分P视频文件,以及对视频分P文件的名称修改,还有对该视频(投搞的视频)的标题,封面,标签,简介的更改。
注意
:分P文件的文件名是可以修改的:
- 如果这个投稿视频的 videoId 是空的,就说明这是一个新增的视频投稿。
- 否则,这个投稿视频应该是进行修改的。
- 根据 videoId 和 userId 查询数据库中该投稿视频的分P视频文件;将分P视频文件 uploadFileList 根据 uploadId 属性(也就是分P视频的上传Id)放入一个Map中,这样可以通过uploadId快速查找对应的VideoInfoFilePost对象(分P视频文件)。如果存在多个具有相同uploadId的对象,后面的会覆盖前面的。
- 用 updateFileName 来标记是否有分P视频文件的文件名被修改了。
- 遍历数据库中的分P视频文件,如果数据库中存在的分P视频文件,在上传的分P视频中不存在,说明此次上传时,将其删除了,所以加入删除列表中。 否则,查看当前遍历的数据库中的分P视频文件的文件名是否与上传的分P视频文件名相同,如果不相同,将 updateFileName 标记为 true(表示有修改)。
- 从uploadFileList(本次上传的分P视频文件)中筛选出所有fileId属性为null的对象,并将这些对象收集到新增分P视频文件的列表中。更新投稿视频的最后一次修改时间。
- 通过 changeVideoInfo() 判断这个投稿视频的标题,封面,标签,简介是否有更改:
- 如果有新增的分P视频文件,那么该投稿视频必须更新状态为转码中;如果没有新增的分P视频,但有修改,则该投稿视频更新状态为审核中。
- 最后通过 mapper 对这个投稿视频进行修改。
—————————————————————————————————————————————————
以上都是在上传视频过程中,对投稿视频 VideoInfoPost 的操作新增和修改操作。
接下来是对投稿视频中的分P视频文件 VideoInfoFilePost 的操作:
-
前面的操作中,已经将要删除的分P视频文件存放在了 deleteFileList 中,通过 mapper 对数据库中的deleteFileList 文件进行删除。
-
同时,也要删除磁盘中的分P视频文件。最好是将要删除的视频加入到消息队列中,通过消息队列慢慢地去删除这个文件,因为这个要删除的视频文件可能很大,而这整个保存视频的操作是在一个事务中的,事务有超时时间,转码操作也一样,也需要放到消息队列中。
不用引入 MQ,Redis 本身也可以做轻量级的消息队列。
- 如果是新增的分P视频文件,要设置 FileId,更新状态类型,转码状态:
- 通过 mapper 批量删除或修改。
将新增的分P视频文件也放到消息队列中,让它自己慢慢转码。
总结
今天的难点是上传投稿中对于上传的视频以及上传视频中的分P视频文件的处理。
要不断看代码才能理解。