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 );}}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/51337.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JVM 运行时内存结构简介

JVM 运行时内存结构简介 一、前言二、JVM 运行时内存结构2.1 线程隔离数据区&#xff1a;2.2 线程共享数据区&#xff1a; 三、JVM 内存区域划分1. 程序计数器&#xff08;PC&#xff09;2. 虚拟机栈3. 本地方法栈4. Java 堆5. 方法区6. 运行时常量池 附录 一、前言 JVM&#…

【C#】【EXCEL】Bumblebee/Classes/ExColumn.cs

文章目录 Bumblebee/Classes/ExColumn.csFlow diagramDescriptionCode Bumblebee/Classes/ExColumn.cs Flow diagram #mermaid-svg-6WUm4r0wDJG9uelI {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-6WUm4r0wDJG9ue…

手撕C++类和对象(中)

1.类的默认成员函数 默认成员函数就是⽤⼾没有显式实现&#xff0c;编译器会⾃动⽣成的成员函数称为默认成员函数。⼀个类&#xff0c;我 们不写的情况下编译器会默认⽣成以下6个默认成员函数&#xff0c;需要注意的是这6个中最重要的是前4个&#xff0c;最 后两个取地址重载不…

Linux 内核源码分析---IPv6 数据包

IPv6是英文“Internet Protocol Version 6”&#xff08;互联网协议第6版&#xff09;的缩写&#xff0c;是互联网工程任务组&#xff08;IETF&#xff09;设计的用于替代IPv4的下一代IP协议&#xff0c;其地址数量号称可以为全世界的每一粒沙子编上一个地址。 由于IPv4最大的…

ES6 -- 总结 03

Es6的模块化 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title> </head>…

鸿蒙Harmony开发——设备发烫问题分析

&#xff1b; 本文字数&#xff1a;4207字 预计阅读时间&#xff1a;25分钟 设备过热问题是影响用户体验和设备性能的重要因素。过热不仅会导致性能下降&#xff0c;还可能损坏硬件。因此&#xff0c;开发者需要及时发现、分析并解决这一问题。本文将首先介绍评估设备过热的关键…

文心快码(Baidu Comate)初体验

文心快码&#xff08;Baidu Comate&#xff09;初体验 1文心快码简介和安装&#xff1a;简要介绍文心快码&#xff08;Baidu Comate&#xff09;、安装方法、使用方法等&#xff1b; Baidu Comate 是由百度自主研发&#xff0c;基于文心大模型&#xff0c;结合百度丰富的编程现…

C/C++逆向:寻找main函数(Debug-x86)

在程序的逆向分析中&#xff0c;寻找main函数在逆向分析中是非常重要的&#xff0c;它是程序的核心执行点&#xff0c;从这里开始&#xff0c;程序的主要逻辑开始展开&#xff1b;在这边我们需要明确两个概念&#xff1a;用户入口&#xff08;User Entry Point&#xff09; 和 …

(十二)Flink Table API

目录 Table API 案例 Table API 连接操作 Table API 是批处理和流处理的统一的关系型 API。Table API 的查询不需要修改代码就可以采用批输入或流输入来运行。Table API 是 SQL 语言的超集,并且是针对 Apache Flink 专门设计的。Table API 集成了 Scala,Java 和 Python 语言…

WIN 10 添加右键菜单(VSCode 打开当前目录)

WIN 10 添加右键菜单&#xff08;VSCode 打开当前目录&#xff09; 前言最终效果操作步骤 前言 每次打开代码都需要先打开 VSCode&#xff0c;再选择最近打开的项目或者浏览打开项目&#xff0c;感觉比较难找。所以自己添加了右键命令。 最终效果 操作步骤 cmd 打开注册表 找…

【Linux 从基础到进阶】Ceph分布式存储系统搭建

Ceph分布式存储系统搭建 引言 随着数据量的爆炸式增长,传统的存储解决方案逐渐暴露出扩展性差、成本高、管理复杂等问题。Ceph是一种高性能、可扩展的开源分布式存储系统,能够为对象存储、块存储和文件系统提供统一的存储平台。它基于无中心的架构设计,具有高可用性、可靠…

PyTorch 基础学习(13)- 混合精度训练

系列文章&#xff1a; 《PyTorch 基础学习》文章索引 基本概念 混合精度训练是深度学习中一种优化技术&#xff0c;旨在通过结合高精度&#xff08;torch.float32&#xff09;和低精度&#xff08;如 torch.float16 或 torch.bfloat16&#xff09;数据类型的优势&#xff0c;…

【Python】自然语言处理(NLP)技术简介

紧紧握着 青花信物 信守着承诺 离别总在 失意中度过 记忆油膏 反复涂抹 无法愈合的伤口 你的回头 划伤了沉默 &#x1f3b5; 周传雄《青花》 自然语言处理&#xff08;NLP&#xff09;技术是一种使计算机能够理解和处理人类自然语言的技术。以下是一些NLP…

appium学习记录

免责声明 本文内容仅供参考&#xff0c;将appuim与爬虫技术相结合可能违反某些app的使用条款和法律法规。作者不对因此产生的法律问题或技术风险负责。建议读者在进行爬取操作前&#xff0c;充分了解相关法律法规并确保合规。 1、初识appium 背景&#xff1a;部分APP需要反编译…

C#用户控件usercontrol中的子控件事件及属性的传递

也不知道这个标题怎么写&#xff0c;但是问题是个老问题&#xff0c;大家都可能遇到过&#xff0c;不过有同学问到&#xff0c;那就写出来。其实很简单。只不过有的同学看了其他博文后脑子还是懵懵的。所以这里就分两部分来说明一下。 文章目录 一、属性的传递1、原理2、步骤3…

tensorflow新建op (cpp)

为什么使用cpp新建op 一些操作表示成现有操作的组合不好实现或者无法实现。已有操作的组合效率不高。想要自定义一些基本操作的组合&#xff0c;因为未来编译器做这种融合可能会比较困难。 如何使用cpp新建op 注册op&#xff0c;注册op会定义一个接口&#xff08;规范&#…

Mac M1Pro 安装Java性能监控工具VisualVM 2.1.9

本地已经安装了java8&#xff0c;在终端输入jvisualvm提示没有安装 zhiniansara ~ % jvisualvm The operation couldn’t be completed. Unable to locate a Java Runtime that supports jvisualvm. Please visit http://www.java.com for information on installing Java.官网…

RPA自动化流程机器人助力企业财务数字化转型

在数字经济时代&#xff0c;企业需要快速响应市场变化&#xff0c;而财务数字化转型是企业适应现代商业环境、提升竞争力的必要步骤。财务数字化转型不仅涉及企业财务能力的提升&#xff0c;推动了财务管理与决策模式的转变。RPA自动化流程机器人因其能通过自动化技术帮助企业实…

[云计算] 虚拟化笔记

原著&#xff1a; 韩冰&#xff0c;[云计算课程]&#xff0c; 有删改。 目的 对 IT 资源简化&#xff0c;用户通过标准接口访问。 资源是提高一定功能的实现 。可以是硬件&#xff0c; 如CPU, 也可以是软件。 发展史 1961 IBM CPU 分时间片&#xff0c; 一个CPU 虚拟化为多…

【Nature】在科研中应用ChatGPT:如何与数据对话

随着人工智能技术的迅猛发展&#xff0c;大型语言模型&#xff08;LLMs&#xff09;正逐渐成为科研领域的一种创新工具。这些模型通过自然语言处理技术&#xff0c;使得研究人员能够以直观的方式与数据进行交互&#xff0c;从而简化了数据分析和解释的过程。在《自然》杂志2024…