当前位置: 首页 > news >正文

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

 参考博客:

        1. Java 视频流分段返回

1. java 拉取 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. 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 );}}}

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 小程序面试题一
  • 【SAM下游任务微调】TS-SAM: Fine-Tuning Segment-Anything Model for Downstream Tasks
  • DDoS攻击的应对策略
  • 小程序学习day13-API Promise化、全局数据共享(状态管理)、分包
  • 探索安全领域的新星:哈希函数SHA3-512
  • 基于深度学习的高效模型压缩
  • FPGA开发——IIC实现简单的串口回环
  • Edge-TTS:微软推出的,免费、开源、支持多种中文语音语色的AI工具[Python代码]
  • Windows连接虚拟机中的mysql5失败
  • 跨域解决 | 面试常问问题
  • openGauss极简版单节点安装
  • 专题---自底向上的计算机网络(数据链路层)
  • 在国产芯片上实现YOLOv5/v8图像AI识别-【2.5】yolov8使用C++部署在RK3588更多内容见视频
  • Swift 可选链
  • 微服务实战系列之玩转Docker(十三)
  • 【162天】黑马程序员27天视频学习笔记【Day02-上】
  • 0x05 Python数据分析,Anaconda八斩刀
  • ES6系统学习----从Apollo Client看解构赋值
  • FineReport中如何实现自动滚屏效果
  • isset在php5.6-和php7.0+的一些差异
  • Mac 鼠须管 Rime 输入法 安装五笔输入法 教程
  • Meteor的表单提交:Form
  • mysql_config not found
  • MySQL几个简单SQL的优化
  • Nodejs和JavaWeb协助开发
  • python 学习笔记 - Queue Pipes,进程间通讯
  • Vue UI框架库开发介绍
  • 安卓应用性能调试和优化经验分享
  • 深入浅出Node.js
  • 使用parted解决大于2T的磁盘分区
  • 新版博客前端前瞻
  • 新书推荐|Windows黑客编程技术详解
  • 最近的计划
  • 好程序员web前端教程分享CSS不同元素margin的计算 ...
  • ​猴子吃桃问题:每天都吃了前一天剩下的一半多一个。
  • ###51单片机学习(2)-----如何通过C语言运用延时函数设计LED流水灯
  • #php的pecl工具#
  • #Spring-boot高级
  • #如何使用 Qt 5.6 在 Android 上启用 NFC
  • (003)SlickEdit Unity的补全
  • (007)XHTML文档之标题——h1~h6
  • (day 12)JavaScript学习笔记(数组3)
  • (Oracle)SQL优化技巧(一):分页查询
  • (php伪随机数生成)[GWCTF 2019]枯燥的抽奖
  • (板子)A* astar算法,AcWing第k短路+八数码 带注释
  • (分布式缓存)Redis持久化
  • (附源码)springboot建达集团公司平台 毕业设计 141538
  • (力扣)1314.矩阵区域和
  • (七)glDrawArry绘制
  • (学习日记)2024.03.25:UCOSIII第二十二节:系统启动流程详解
  • (一)eclipse Dynamic web project 工程目录以及文件路径问题
  • (转)es进行聚合操作时提示Fielddata is disabled on text fields by default
  • ... 是什么 ?... 有什么用处?
  • .NET 4.0中使用内存映射文件实现进程通讯
  • .NET Core 成都线下面基会拉开序幕