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();
            }
        }
    }
相关推荐
Renascence.4092 分钟前
力扣--649.Dota2参议院
java·数据结构·算法·leetcode
VaporGas10 分钟前
掌握Java封装:以猜拳小游戏为例,深入理解OOP
java·开发语言·学习·面向对象编程·oop·猜拳游戏·封装思想
小小工匠16 分钟前
加密与安全_ sm-crypto 国密算法sm2、sm3和sm4的Java库
java·算法·安全·sm2·sm3·sm4
小tenten38 分钟前
js延迟for内部循环方法
开发语言·前端·javascript
程序员大金41 分钟前
基于SpringBoot+Vue+MySQL的垃圾分类回收管理系统
java·vue.js·spring boot·后端·mysql·mybatis
幻影浪子1 小时前
Web网站常用测试工具
前端·测试工具
陈小唬1 小时前
树形结构构建的两种方式
java·数据库·算法
CJH~1 小时前
Java入门:09.Java中三大特性(封装、继承、多态)01
java·开发语言·单例模式
打工人9961 小时前
反编译app
java
coding侠客1 小时前
Spring Boot 注解探秘:常用配置值读取注解的魔力
java·spring boot·后端·spring·spring cloud