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

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

minio安装

Windows中Minio的安装和使用_minio登录地址-CSDN博客

minio JavaApi

http://t.csdn.cn/HI0aw

代码参考

https://www.pudn.com/news/627cadde5981aa38ef847274.html

断点续传| ProcessOn免费在线作图,在线流程图,在线思维导图

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


 /**
     * 视频断点续播预览
     * @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();
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值