java 使用 aws s3 sdk 通过分段下载来实现 html 页面 video 的断点播放、拖动进度播放

embedded/2024/10/19 14:37:13/
htmledit_views">

 参考博客:

        1. Java 视频流分段返回

1. html" title=java>java 拉取 html" title=aws>aws s3 视频流返回给浏览器:

    @Overridepublic void playVideo(Long fileLength,String key,HttpServletRequest request,HttpServletResponse response) {OutputStream outputStream = null;S3ObjectInputStream s3ObjectInputStream = null;try {outputStream = response.getOutputStream();// 获取从哪个字节开始读取文件String rangeHeader = request.getHeader("Range");if (rangeHeader == null) {response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Required 'Range' header is missing");return;}long startByte = 0;long endByte = fileLength - 1;if (rangeHeader.startsWith("bytes=")) {String[] rangeParts = rangeHeader.substring(6).split("-");startByte = Long.parseLong(rangeParts[0]);endByte = rangeParts.length > 1 ? startByte : fileLength - 1;}if (startByte > endByte || startByte < 0 || endByte >= fileLength) {response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE, "Requested range not satisfiable");return;}// 设置响应头response.setHeader("Content-Type", "video/mp4");response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);response.setHeader("Content-Range", "bytes " + startByte + "-" + endByte + "/" + fileLength);// 从S3获取视频流GetObjectRequest getObjectRequest = new GetObjectRequest(this.fileBucket, key).withRange(startByte, endByte + 1);S3Object s3Object = this.amazonS3.getObject(getObjectRequest);s3ObjectInputStream = s3Object.getObjectContent();// 将视频流响应给客户端byte[] buffer = new byte[1024 * 1024]; // 使用1MB的缓冲区int bytesRead;long totalBytesRead = 0;while ((bytesRead = s3ObjectInputStream.read(buffer)) != -1 && totalBytesRead <= (endByte - startByte + 1)) {outputStream.write(buffer, 0, bytesRead);totalBytesRead += bytesRead;}response.setContentLength((int) (endByte - startByte + 1)); // 设置实际返回的数据长度} catch (Exception e) {// 处理异常log.error( CommonConstans.EXCEPTION_LOG_PREFIX,e );// 处理异常try {response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Internal server error");}catch ( Exception e ){log.error( CommonConstans.EXCEPTION_LOG_PREFIX,e );}}finally {if( outputStream != null ){try {outputStream.close();}catch ( Exception e1 ){log.error( CommonConstans.EXCEPTION_LOG_PREFIX,e1 );}}if( s3ObjectInputStream != null ){try {s3ObjectInputStream.close();}catch ( Exception e1 ){log.error( CommonConstans.EXCEPTION_LOG_PREFIX,e1 );}}}}

2. html" title=java>java读物本地视频文件返回给浏览器:

html" title=java>java">    @Overridepublic void playVideo(HttpServletRequest request, HttpServletResponse response) {RandomAccessFile randomAccessFile = null;OutputStream outputStream = null;try {response.reset();// File file = new File("D:\\素材\\视频\\crazy_max_small.mp4");File file = new File("D:\\视频\\888.mp4");long fileLength = file.length();// 随机读文件randomAccessFile = new RandomAccessFile(file, "r");//获取从那个字节开始读取文件String rangeString = request.getHeader("Range");System.out.println(rangeString);long range=0;if (rangeString!=null) {range = Long.valueOf(rangeString.substring(rangeString.indexOf("=") + 1, rangeString.indexOf("-")));}//获取响应的输出流outputStream = response.getOutputStream();//设置内容类型response.setHeader("Content-Type", "video/mp4");//返回码需要为206,代表只处理了部分请求,响应了部分数据response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);// 移动访问指针到指定位置randomAccessFile.seek(range);// 每次请求只返回1MB的视频流byte[] bytes = new byte[1024 * 1024];int len = randomAccessFile.read(bytes);//设置此次相应返回的数据长度response.setContentLength(len);//设置此次相应返回的数据范围response.setHeader("Content-Range", "bytes "+range+"-"+(fileLength-1)+"/"+fileLength);// 将这1MB的视频流响应给客户端outputStream.write(bytes, 0, len);System.out.println("返回数据区间:【"+range+"-"+(range+len)+"】");}catch ( Exception e ){log.error( CommonConstans.EXCEPTION_LOG_PREFIX,e );// 处理异常try {response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Internal server error");}catch ( Exception e1 ){log.error( CommonConstans.EXCEPTION_LOG_PREFIX,e1 );}}finally {if( outputStream != null){try {outputStream.close();}catch ( Exception e){log.error( CommonConstans.EXCEPTION_LOG_PREFIX,e );}}if( randomAccessFile != null ){try {randomAccessFile.close();}catch ( Exception e ){log.error( CommonConstans.EXCEPTION_LOG_PREFIX,e );}}}


http://www.ppmy.cn/embedded/101450.html

相关文章

如何本地搭建 Whisper 语音识别模型?一文解决

Whisper 是 OpenAI 开发的强大语音识别模型&#xff0c;适用于多种语言的语音转文字任务。要在本地搭建 Whisper 模型&#xff0c;需要完成以下几个步骤&#xff0c;确保模型在你的设备上顺利运行。 1. 准备环境 首先&#xff0c;确保你的系统上安装了 Python&#xff08;版本 …

34次8.22(docker基础)

高并发集群&#xff0c;eleme后端的登录模块 1.数据库 1.主从复制&#xff08;高可用&#xff09; 2.传统的主从复制 3.gtids事务型的主从复制 4.注意 1.server_id唯一 2.8.x版本需要get_aal_pub_key 3.5.x不需要 4.change master to 5.stop | start slave 5.非交互…

sqli-labs靶场通关攻略(31-35关)

第31关&#xff08; ") 闭合&#xff09; 查数据库 ?id") union select 1,2,database() -- 查表 ?id") union select 1,2,group_concat(table_name) from information_schema.tables where table_schemasecurity-- 查列 ?id") union select 1,2,gro…

linux常见基础命令

Linux基础命令 (下面这些命令都是最常见的命令.更复杂的会在之后的C语言学习陆续深入) 1、 pwd 功能&#xff1a; print work directory的缩写&#xff0c;显示当前目录的绝对路径 2、 cd 功能&#xff1a; change directory的缩写&#xff0c;切换目录 绝对路径&#xff1a;以…

springboot后端开发-自定义参数校验器

背景 在使用springboot进行后端开发的时候&#xff0c;经常会遇到数据校验的问题&#xff0c; 有时候可能默认的校验器不足以满足自己的需求&#xff0c; 这个时候就需要开发一个自己的校验器 在 Spring Boot 中自定义参数校验器通常涉及以下几个步骤&#xff1a; 1. 定义注解…

使用命令模式实现撤销与重做功能的完整指南

使用命令模式实现撤销与重做功能的完整指南 命令模式是一种行为型设计模式&#xff0c;它将请求封装成对象&#xff0c;以便于对请求进行参数化、排队和记录。命令模式不仅有助于实现撤销和重做功能&#xff0c;还能提高系统的灵活性和可维护性。在本文中&#xff0c;我们将详…

【JUC并发编程系列】深入理解Java并发机制:CAS算法与原子类在Java中的实践应用(二、CAS)

文章目录 【JUC并发编程系列】深入理解Java并发机制&#xff1a;CAS算法与原子类在Java中的实践应用(二、CAS)1. 同步之原子类&#xff08;Atomic类&#xff09;2. 使用atomicInteger计数3. 使用atomicInteger底层原理3. compareAndSet原理分析3.1 手写AtomicInteger3.2 手写Lo…

刘海屏的优雅回归?华为Mate 70 Pro定义新美学

在智能手机的发展历程中&#xff0c;华为Mate系列一直是高端旗舰的代表。而今&#xff0c;华为Mate 70 Pro的神秘面纱终于揭开&#xff0c;其回归的刘海屏设计和独特的寰宇舷窗设计&#xff0c;再次将华为的设计理念推向了新的高度。 刘海屏的回归&#xff1a;经典与创新的融合…