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

server/2024/10/19 1:21:31/
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/server/108259.html

相关文章

zookeeper服务器动态上下线监听案例

zookeeper服务器动态上下线监听案例 文档 linux安装java -centos安装java -linux配置java环境变量zookeeper单机安装zookeeper集群安装zookeeper客户端命令行操作、节点类型及监听器zookeeper集群写数据原理java操作zookeeper 说明 两种角色&#xff1a;服务器、客户端 客户…

20240827软考架构-------软考76-80答案解析

每日打卡题76-80 76、【2012年真题】 难度&#xff1a;一般 基于场景的架构分析方法(Scenarios-based Architecture Analysis Method&#xff0c;SAAM)是卡耐基梅隆大学软件工程研究所的Kazman等人于1983年提出的一种非功能质量属性的架构分析方法&#xff0c;是最早形成文档并…

清除系统缓存提高写盘速度的tips

sync; echo 3 > /proc/sys/vm/drop_caches 上面是一个常用于 Linux 系统的命令组合&#xff0c;主要用于清理内存中的缓存。下面是对这条命令的详细解释&#xff1a; sync sync 命令用于将所有未写入磁盘的缓存数据写入磁盘。Linux 操作系统会将一些数据保存在内存中&#x…

国内券商有没有提供股票程序化交易接口的

国内券商股票程序化交易接口概述 股票程序化交易在金融市场中日益重要&#xff0c;而国内券商在这方面的服务和接口提供情况备受关注。 券商提供的接口方式 券商提供的接口方式多种多样。有些券商提供自研系统&#xff0c;如国信的云核用 C编程&#xff0c;速度较快但入门门…

OpenGuass under Ubuntu_22.04 install tutorial

今天开始短学期课程&#xff1a;数据库课程设计。今天9点左右在SL1108开课&#xff0c;听陈老师讲授了本次短学期课程的要求以及任务安排&#xff0c;随后讲解了国产数据库的三层架构的逻辑。配置了大半天才弄好&#xff0c;放一张成功的图片&#xff0c;下面开始记录成功的步骤…

okhttp异步请求连接阻塞问题排查

表现&#xff1a; 使用okhttp请求外部大模型接口时&#xff0c;当并发在2-5左右&#xff0c;出现请求被阻塞在建立http连接之前&#xff0c;阻塞时间超长&#xff08;>20s&#xff0c;从日志看有160s存在&#xff09;。但是httpconfig的connTimeout时间配置为100s&#xff…

git命令

git checkout -b new-feature [从更新后的master分支创建新的分支] git pull origin master [同步远端master分支&#xff0c;将远程主机的最新内容拉下来后直接合并] [git pull git fetch git merge] git checkout master [切换分支] git fetch origin [更新所有远端分支…

Android原生JobSchedulerContext内存泄漏导致设备重启的现象

一、现象&#xff1a;原生JobSchedulerContext内存泄漏占比 JobServiceContext内存泄露导致ServiceDispatcher也跟着一起内存堆积 二、现象日志&#xff1a; 内存泄漏的日志关键信息&#xff1a;ActivityManager: Unbind failed: could not find connection for android.app.…