minio 大视频观看,下载

在线观看

java 复制代码
 /**
     * 下载视频文件 fileName文件路径名称  文件路径 BacketName/video/1111.mp4   需要截取桶名后面的路径  video/1111.mp4 video前面不要带/   
     *
     * @param fileName
     * @param request
     * @param response
     */
    public  void play(String fileName, HttpServletRequest request, HttpServletResponse response) {
        if (StringUtils.isNotBlank(fileName)) {
            log.info("download:" + fileName);
            String range = request.getHeader("Range");
            log.info("current request rang:" + range);
            //获取文件信息
            // 调用statObject()来判断对象是否存在。
            // 如果不存在, statObject()抛出异常,
            // 否则则代表对象存在。
            StatObjectResponse statObjectResponse = null;
            try {
                statObjectResponse = client.statObject(
                        StatObjectArgs.builder().bucket(minioConfig.getBucketName()).object(fileName).build());
            } catch (ErrorResponseException e1) {
                e1.printStackTrace();
            } catch (InsufficientDataException e1) {
                e1.printStackTrace();
            } catch (InternalException e1) {
                e1.printStackTrace();
            } catch (InvalidKeyException e1) {
                e1.printStackTrace();
            } catch (InvalidResponseException e1) {
                e1.printStackTrace();
            } catch (IOException e1) {
                e1.printStackTrace();
            } catch (NoSuchAlgorithmException e1) {
                e1.printStackTrace();
            } catch (ServerException e1) {
                e1.printStackTrace();
            } catch (XmlParserException e1) {
                e1.printStackTrace();
            }
            System.out.println(statObjectResponse);
            //开始下载位置
            long startByte = 0;
            //结束下载位置
            long endByte = statObjectResponse.size() - 1;
            log.info("文件开始位置:{},文件结束位置:{},文件总长度:{}", startByte, endByte, statObjectResponse.size());
            //有range的话
            if (StringUtils.isNotBlank(range) && range.contains("bytes=") && range.contains("-")) {
                range = range.substring(range.lastIndexOf("=") + 1).trim();
                String[] ranges = range.split("-");
                try {
                    //判断range的类型
                    if (ranges.length == 1) {
                        //类型一:bytes=-2343
                        if (range.startsWith("-")) {
                            endByte = Long.parseLong(ranges[0]);
                        }
                        //类型二:bytes=2343-
                        else if (range.endsWith("-")) {
                            startByte = Long.parseLong(ranges[0]);
                        }
                    }
                    //类型三:bytes=22-2343
                    else if (ranges.length == 2) {
                        startByte = Long.parseLong(ranges[0]);
                        endByte = Long.parseLong(ranges[1]);
                    }

                } catch (NumberFormatException e) {
                    startByte = 0;
                    endByte = statObjectResponse.size() - 1;
                    log.error("Range Occur Error, Message:" + e.getLocalizedMessage());
                }
            }

            //要下载的长度
            long contentLength = endByte - startByte + 1;
            //文件类型
            String contentType = request.getServletContext().getMimeType(fileName);

            //解决下载文件时文件名乱码问题
            byte[] fileNameBytes = fileName.getBytes(StandardCharsets.UTF_8);
            fileName = new String(fileNameBytes, 0, fileNameBytes.length, StandardCharsets.ISO_8859_1);

            //各种响应头设置
            //支持断点续传,获取部分字节内容:
            response.setHeader("Accept-Ranges", "bytes");
            //http状态码要为206:表示获取部分内容
            response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
            response.setContentType(contentType);
            response.setHeader("Last-Modified", statObjectResponse.lastModified().toString());
            //inline表示浏览器直接使用,attachment表示下载,fileName表示下载的文件名
            response.setHeader("Content-Disposition", "inline;filename=" + fileName);
            response.setHeader("Content-Length", String.valueOf(contentLength));
            //Content-Range,格式为:[要下载的开始位置]-[结束位置]/[文件总大小]
            response.setHeader("Content-Range", "bytes " + startByte + "-" + endByte + "/" + statObjectResponse.size());
            response.setHeader("ETag", "\"".concat(statObjectResponse.etag()).concat("\""));

            try {
                GetObjectResponse stream = client.getObject(
                        GetObjectArgs.builder()
                                .bucket(statObjectResponse.bucket())
                                .object(statObjectResponse.object())
                                .offset(startByte)
                                .length(contentLength)
                                .build());
                BufferedOutputStream os = new BufferedOutputStream(response.getOutputStream());
                byte[] buffer = new byte[1024*40];
                int len;
                while ((len = stream.read(buffer)) != -1) {
                    os.write(buffer, 0, len);
                }
                os.flush();
                os.close();
                response.flushBuffer();
                log.info("下载完毕");
            } catch (ClientAbortException e) {
                log.warn("用户停止下载:" + startByte + "-" + endByte);
                //捕获此异常表示拥护停止下载
            } catch (IOException e) {
                e.printStackTrace();
                log.error("用户下载IO异常,Message:{}", e.getLocalizedMessage());
            } catch (XmlParserException e1) {
                e1.printStackTrace();
            } catch (ServerException e1) {
                e1.printStackTrace();
            } catch (NoSuchAlgorithmException e1) {
                e1.printStackTrace();
            } catch (InsufficientDataException e1) {
                e1.printStackTrace();
            } catch (InvalidKeyException e1) {
                e1.printStackTrace();
            } catch (InvalidResponseException e1) {
                e1.printStackTrace();
            } catch (ErrorResponseException e1) {
                e1.printStackTrace();
            } catch (InternalException e1) {
                e1.printStackTrace();
            }
        }
    }
相关推荐
带刺的坐椅14 小时前
MCP 进化:让静态 Tool 进化为具备“上下文感知”的远程 Skills
java·ai·llm·agent·solon·mcp·tool-call·skills
java1234_小锋15 小时前
Java线程之间是如何通信的?
java·开发语言
张张努力变强15 小时前
C++ Date日期类的设计与实现全解析
java·开发语言·c++·算法
HWL567915 小时前
获取网页首屏加载时间
前端·javascript·vue.js
烟锁池塘柳015 小时前
【已解决】Google Chrome 浏览器报错 STATUS_ACCESS_VIOLATION 的解决方案
前端·chrome
速易达网络15 小时前
基于RuoYi-Vue 框架美妆系统
前端·javascript·vue.js
LYS_061815 小时前
RM赛事C型板九轴IMU解算(4)(卡尔曼滤波)
c语言·开发语言·前端·卡尔曼滤波
while(1){yan}15 小时前
Spring事务
java·数据库·spring boot·后端·java-ee·mybatis
毕设源码-赖学姐16 小时前
【开题答辩全过程】以 高校社团管理平台为例,包含答辩的问题和答案
java
We་ct16 小时前
LeetCode 151. 反转字符串中的单词:两种解法深度剖析
前端·算法·leetcode·typescript