【Minio】实现视频断点续传功能

619 阅读1分钟

视频预览设置一次只下载3m大小

minio安装

blog.csdn.net/weixin_4557…

minio JavaApi

t.csdn.cn/HI0aw

代码参考

www.pudn.com/news/627cad…

www.processon.com/view/link/5…

最终实例(浏览器会根据range自动循环调用接口)

image.png

```/**

* 视频断点续播预览

* @param bucketName

* @param fileName

* @param request

* @param res

*/

public void videoPreview(String bucketName,

String fileName,

HttpServletRequest request,

HttpServletResponse res) {

try {

String fileType = fileName.substring(fileName.lastIndexOf(".") + 1).toUpperCase(Locale.ROOT);

StatObjectResponse statObjectResponse = minioClient.statObject(

StatObjectArgs.builder()

.bucket(bucketName)

.object(fileName)

.build());

long fileSize = statObjectResponse.size();

final long bufferStep = 1024 * 1024 * 3; // 流区间

long startPos = 0; // 流起始位置

long endPos = fileSize - 1; // 流结束位置

String rangeHeader = request.getHeader("Range");

if (!ObjectUtils.isEmpty(rangeHeader) && rangeHeader.startsWith("bytes=")) {

try {

// 断点续传 状态码206

res.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);

// 情景一:RANGE: bytes=2000070- 情景二:RANGE: bytes=2000070-2000970

String numRang = request.getHeader("Range").replaceAll("bytes=", "");

if (numRang.startsWith("-")) {

startPos = 0;

endPos = endPos - Long.parseLong(new String(numRang.getBytes(StandardCharsets.UTF_8), 1,

numRang.length() - 1));

} else if (numRang.endsWith("-")) {

startPos = Long.parseLong(new String(numRang.getBytes(StandardCharsets.UTF_8), 0,

numRang.length() - 1));

endPos = fileSize - 1;

} else {

String[] strRange = numRang.split("-");

if (strRange.length == 2) {

startPos = Long.parseLong(strRange[0].trim());

endPos = Long.parseLong(strRange[1].trim());

}

}

if (startPos < 0 || endPos < 0 || endPos >= fileSize || startPos > endPos) {

// range不满足

res.setStatus(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);

return;

}

} catch (NumberFormatException e) {

LOGGER.error(request.getHeader("Range") + " is not Number!");

startPos = 0;

}

}

if (fileType.contains("MP4"))

res.setContentType("video/mp4");

else if (fileType.contains("AVI"))

res.setContentType("video/avi");

else if (fileType.contains("WEBM"))

res.setContentType("video/webm");

else if (fileType.contains("wmv"))

res.setContentType("video/x-ms-wmv");

else if (fileType.contains("mkv"))

res.setContentType("video/x-matroska");

if (endPos - startPos + 1 > bufferStep) {

endPos = startPos + bufferStep - 1; //设置为定长流区间

}

if (endPos >= fileSize)

endPos = fileSize - 1;

long resContentLength = bufferStep; // response内容长度

if (endPos == fileSize - 1)

resContentLength = endPos - startPos + 1; // 设置为文件剩余的实际长度

res.setHeader("Accept-Ranges", "bytes");

res.setHeader("Content-Range", String.format("bytes %d-%d/%d", startPos, endPos, fileSize));

res.addHeader("Content-Length", String.valueOf(resContentLength));

res.addHeader("Content-Type", "video/mp4");

GetObjectArgs objectArgs2 = GetObjectArgs.builder().bucket(bucketName)

.object(fileName)

.offset(startPos)

.length(bufferStep)

.build();

InputStream tmpStream = minioClient.getObject(objectArgs2);

ServletOutputStream stream = res.getOutputStream();

IOUtils.copy(tmpStream, stream);

stream.flush();

} catch (Exception e) {

e.printStackTrace();

}

}