前言
这一篇说点题外话,一个视频网站,除了直播模块,其他最重要的一个功能就是播放视频,但是如何用springboot实现视频的播放接口呢?这就是本篇要解决的问题
springboot 视频的上传和播放
首先修改application.yml,因为springboot默认的上传文件的大小有限制
Spring:
servlet:
multipart:
max-file-size: -1
max-request-size: -1
视频的上传功能
视频的上传功能其实本质上就是文件的上传功能
controller
@Resource
private VideoService videoService;
@PostMapping(value = "/uploadFile")
@ResponseBody
@ApiOperation("文件上传接口")
@ApiImplicitParam(name = "fileName", value = "文件字段名称")
public ReturnMsg uploadFile(@RequestParam("fileName") MultipartFile file) {
return videoService.saveFile(file);
}
service
@Value("${video_path}")
private String videoPath;
@Resource
private VoiceUploadFileMapper voiceUploadFileMapper;
@Override
public ReturnMsg saveFile(MultipartFile file) {
String date = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
String videoPathNow = videoPath + "/" + date + "/";
VoiceUploadFile uploadFile = new VoiceUploadFile();
//判断文件是否为空
if (file.isEmpty()) {
return ReturnMsg.fail(-1, "上传文件不可为空");
}
// 获取文件名
String fileName = file.getOriginalFilename();
uploadFile.setFileType(fileName.substring(fileName.lastIndexOf(".") + 1));
fileName = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + "_" + fileName;
uploadFile.setFileName(fileName);
//加个时间戳,尽量避免文件名称重复
String path = videoPathNow + fileName;
uploadFile.setFilePath(path);
uploadFile.setCreateTime(new Date());
uploadFile.setUpdateTime(new Date());
//创建文件路径
File dest = new File(path);
//判断文件是否已经存在
if (dest.exists()) {
return ReturnMsg.fail(-2, "文件已经存在");
}
//判断文件父目录是否存在
if (!dest.getParentFile().exists()) {
dest.getParentFile().mkdir();
}
try {
//上传文件
file.transferTo(dest); //保存文件
saveToDB(uploadFile);
} catch (IOException e) {
return ReturnMsg.fail(-3, "上传失败:" + e.getMessage());
}
return ReturnMsg.success(0, "上传成功");
}
private void saveToDB(VoiceUploadFile uploadFile) {
voiceUploadFileMapper.insertSelective(uploadFile);
}
See?就是文件的上传功能,然后保存到数据库,我的数据库设计如下,仅供参考
CREATE TABLE `voice_upload_file` (
`id` int NOT NULL AUTO_INCREMENT,
`file_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`file_path` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`file_type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`file_cover` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`create_time` datetime DEFAULT NULL,
`update_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=26 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
视频的播放接口
视频的播放,本质上也就是文件的下载的功能,但是有一点需要说明下,当用户在播放视频时,如果强制关闭浏览器,这样数据流就会中断,所以要在服务端抛出相应的异常
controller
@GetMapping(value = "playVideo")
@ApiOperation("视频播放接口")
@ApiImplicitParam(name = "name", value = "视频名称")
public String playVideo(HttpServletRequest request, HttpServletResponse response, String name) {
VoiceUploadFile voiceUploadFile = videoService.getVideoByPath(name);
try {
FileInputStream fis = null;
OutputStream os = null;
fis = new FileInputStream(voiceUploadFile.getFilePath());
int size = fis.available(); // 得到文件大小
byte data[] = new byte[size];
fis.read(data); // 读数据
fis.close();
fis = null;
response.setContentType("video/mp4"); // 设置返回的文件类型
os = response.getOutputStream();
os.write(data);
os.flush();
os.close();
os = null;
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
system.out.println("传输异常")
e.printStackTrace();
}
return null;
}
service
@Override
public VoiceUploadFile getVideoByPath(String name) {
VoiceUploadFileExample example = new VoiceUploadFileExample();
example.createCriteria()
.andFileNameEqualTo(name);
return voiceUploadFileMapper.selectByExample(example).get(0);
}
看出保存数据库的好处了吧!
这样在页面输入地址就可以播放了
<div class="video-play">
<video width="400" height="300" controls="controls" ref="video">
<source :src="videoPlay" type="video/mp4" />
<p class="warning">Your browser does not support HTML5 video.</p>
</video>
</div>
playVideo(index, tableData) {
let data = tableData[index];
this.$refs.video.src = API.VIDEO_PLAY_VIDEO + "?name=" + data.fileName;
},
结束!