Spring boot实现视频播放断点续传
Spring boot提供HDFS上的视频播放接口,支持断点续传
视频播放断点续传
HTTP1.1中优化了网络连接的使用,支持在Header中设置range字段,允许请求资源的一部分,并使用返回码 206 “Partial Content” 标识
后端简单实现
@GetMapping("/file/video-preview")
public void videoPreview(HttpServletResponse response,
@RequestParam String filePath,
@RequestHeader String range) throws IOException {
hugeFileService.videoPreview(filePath, range, response);
}
public void videoPreview(String filePath, String range, HttpServletResponse response) throws IOException {
response.reset();
// 自定义getHdfsPath函数生成文件在hdfs上的路径
Path srcPath = new Path(getHdfsPath(filePath));
FSDataInputStream resource = fs.open(srcPath);
// 每次返回的最大数据块大小
long partLen = 1024 * 1024 * 2;
byte[] bytes = new byte[(int) partLen];
// 计算本次返回的数据范围 [start, end]
long fileLen = hdfsFileService.getHdfsFileStatus(srcPath.toString()).getLen();
long start = Long.parseLong(range.substring(range.indexOf("=") + 1, range.indexOf("-")));
long end = Math.min(start + partLen - 1, fileLen-1);
BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
// 随机寻址 定位数据块头
resource.seek(start);
// 计算本次返回的数据块大小
int len = (int) (end - start + 1);
// 由于每次最多读 65535 循环读入数据
int ptr = 0;
while (ptr < len) {
int readLen = Math.min(65535, len - ptr);
resource.readFully(bytes, ptr, readLen);
ptr += readLen;
}
//返回码需要为206,代表只处理了部分请求,响应了部分数据
response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
response.setHeader("Content-Type", "video/mp4");
//设置此次相应返回的数据长度
response.setContentLength(len);
//设置此次相应返回的数据范围
response.setHeader("Content-Range", "bytes " + start + "-" + end + "/" + fileLen);
response.setHeader("Accept-Ranges", "bytes");
// 写入数据到OutputStream
out.write(bytes, 0, len);
out.flush();
out.close();
resource.close();
}
}
前端简单实现(假设点击播放按钮,在一个Modal内部,生成播放视频的代码)
buildVideoShowData = () => {
const { file } = this.props;
const { path } = file;
const url = `http://ip:port/file/video-preview?filePath=${path}`;
return (
<video width="840" height="630"
controls='controls'
preload='auto'
autoPlay={true}
src={url}
loop={true}
>
</video>
)
}
可能遇到的问题
如果视频从开头播放一直没问题,直到最后一段卡死。需要检查后端返回的Http响应中的range是否设置正确
range的end最大为fileLen-1,最后一段需设置为 xxx-fileLen-1/fileLen

浙公网安备 33010602011771号