方案一

//path为本地文件路劲
public void play(String path, HttpServletRequest request, HttpServletResponse response) { RandomAccessFile targetFile = null;
OutputStream outputStream = null;
try {
outputStream = response.getOutputStream();
response.reset();
//获取请求头中Range的值
String rangeString = request.getHeader(HttpHeaders.RANGE); //打开文件
File file = new File(path);
if (file.exists()) {
//使用RandomAccessFile读取文件
targetFile = new RandomAccessFile(file, "r");
long fileLength = targetFile.length();
long requestSize = (int) fileLength;
//分段下载视频
if (StringUtils.hasText(rangeString)) {
//从Range中提取需要获取数据的开始和结束位置
long requestStart = 0, requestEnd = 0;
String[] ranges = rangeString.split("=");
if (ranges.length > 1) {
String[] rangeDatas = ranges[1].split("-");
requestStart = Integer.parseInt(rangeDatas[0]);
if (rangeDatas.length > 1) {
requestEnd = Integer.parseInt(rangeDatas[1]);
}
}
if (requestEnd != 0 && requestEnd > requestStart) {
requestSize = requestEnd - requestStart + 1;
}
//根据协议设置请求头
response.setHeader(HttpHeaders.ACCEPT_RANGES, "bytes");
response.setHeader(HttpHeaders.CONTENT_TYPE, "video/mp4");
if (!StringUtils.hasText(rangeString)) {
response.setHeader(HttpHeaders.CONTENT_LENGTH, fileLength + "");
} else {
long length;
if (requestEnd > 0) {
length = requestEnd - requestStart + 1;
response.setHeader(HttpHeaders.CONTENT_LENGTH, "" + length);
response.setHeader(HttpHeaders.CONTENT_RANGE, "bytes " + requestStart + "-" + requestEnd + "/" + fileLength);
} else {
length = fileLength - requestStart;
response.setHeader(HttpHeaders.CONTENT_LENGTH, "" + length);
response.setHeader(HttpHeaders.CONTENT_RANGE, "bytes " + requestStart + "-" + (fileLength - 1) + "/"
+ fileLength);
}
}
//断点传输下载视频返回206
response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
//设置targetFile,从自定义位置开始读取数据
targetFile.seek(requestStart);
} else {
//如果Range为空则下载整个视频
response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=test.mp4");
//设置文件长度
response.setHeader(HttpHeaders.CONTENT_LENGTH, String.valueOf(fileLength));
} //从磁盘读取数据流返回
byte[] cache = new byte[4096];
try {
while (requestSize > 0) {
int len = targetFile.read(cache);
if (requestSize < cache.length) {
outputStream.write(cache, 0, (int) requestSize);
} else {
outputStream.write(cache, 0, len);
if (len < cache.length) {
break;
}
}
requestSize -= cache.length;
}
} catch (IOException e) {
// tomcat原话。写操作IO异常几乎总是由于客户端主动关闭连接导致,所以直接吃掉异常打日志
//比如使用video播放视频时经常会发送Range为0- 的范围只是为了获取视频大小,之后就中断连接了
log.info(e.getMessage());
}
} else {
throw new RuntimeException("文件路劲有误");
}
outputStream.flush();
} catch (Exception e) {
log.error("文件传输错误", e);
throw new RuntimeException("文件传输错误");
}finally {
if(outputStream != null){
try {
outputStream.close();
} catch (IOException e) {
log.error("流释放错误", e);
}
}
if(targetFile != null){
try {
targetFile.close();
} catch (IOException e) {
log.error("文件流释放错误", e);
}
}
}
}

方案二

/**
* 获取视频流
* @param response
* @param fileName 视频存放信息索引
* @return
*/
@RequestMapping("/getVideo")
public void getVideo(HttpServletRequest request, HttpServletResponse response,String fileName) {
//视频资源存储信息
response.reset();
//获取从那个字节开始读取文件
String rangeString = request.getHeader("Range");
log.info("getVideo获取视频资源:{},读取文件字节:{}",fileName,rangeString);
try {
//获取响应的输出流
OutputStream outputStream = response.getOutputStream();
File file = new File(fileName);
if(file.exists()){
RandomAccessFile targetFile = new RandomAccessFile(file, "r");
long fileLength = targetFile.length();
//播放
if(rangeString != null){ long range = Long.parseLong(rangeString.substring(rangeString.indexOf("=") + 1, rangeString.indexOf("-")));
//设置内容类型
response.setHeader("Content-Type", "video/mov");
//设置此次相应返回的数据长度
response.setHeader("Content-Length", String.valueOf(fileLength - range));
//设置此次相应返回的数据范围
response.setHeader("Content-Range", "bytes "+range+"-"+(fileLength-1)+"/"+fileLength);
//返回码需要为206,而不是200
response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
//设定文件读取开始位置(以字节为单位)
targetFile.seek(range);
}else {//下载 //设置响应头,把文件名字设置好
response.setHeader("Content-Disposition", "attachment; filename="+fileName );
//设置文件长度
response.setHeader("Content-Length", String.valueOf(fileLength));
//解决编码问题
response.setHeader("Content-Type","application/octet-stream");
} byte[] cache = new byte[1024 * 300];
int flag;
while ((flag = targetFile.read(cache))!=-1){
outputStream.write(cache, 0, flag);
}
}else {
String message = "file:"+fileName+" not exists";
//解决编码问题
response.setHeader("Content-Type","application/json");
outputStream.write(message.getBytes(StandardCharsets.UTF_8));
} outputStream.flush();
outputStream.close(); } catch (FileNotFoundException e) { } catch (IOException e) { }
}

java web 传输视频流代码锦集的更多相关文章

  1. 2020 python web开发就业要求锦集

    郑州 Python程序员 河南三融云合信息技术有限公司 6-8k·12薪 7个工作日内反馈 郑州 1个月前 本科及以上2年以上语言不限年龄不限 微信扫码分享 收藏 Python程序员 河南三融云合信息 ...

  2. java Web jsp嵌入代码的三种方式

    1,表达式标签  <%= 2+3%> 唯一有显示功能的标签 作用: 计算表达式的返回值 将表达式的返回值显示到网页中. 注意: 表达式中不能有分号 2,普通脚本标签  <% %> ...

  3. JAVA WEB主流开发工具下载集

    JAVA SEhttp://www.oracle.com/technetwor ... ownloads/index.html eclipsehttp://www.eclipse.org/downlo ...

  4. java web 程序---缓冲代码

    在写验证码的时候,我的验证码是随机的,所以每次点击时,刷新页面,验证码都会改变. 可是,当我点击刷新时,验证码不变,说明,没有缓冲. 这里差三行代码. response.setHeader(" ...

  5. java web 程序---javabean代码,出现错误。奇怪,无法解释的运行问题

    深夜吧.这个点11点半了 写了一个简单的javabean实例,发现没有任何代码书写的错误,但是问题就是程序运行会有问题,然后换一个包,重写一个,问题没了? 请问问题出现在哪里了?巧合?还是操作有误?这 ...

  6. java web 代码

    原 30套JSP网站源代码合集 IT小白白 发布时间: 2012/12/28 14:30 阅读: 272 收藏: 3 点赞: 0 评论: 0 JSP技术是以Java语言作为脚本语言的,JSP网页为整个 ...

  7. [原创]java WEB学习笔记66:Struts2 学习之路--Struts的CRUD操作( 查看 / 删除/ 添加) 使用 paramsPrepareParamsStack 重构代码 ,PrepareInterceptor拦截器,paramsPrepareParamsStack 拦截器栈

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

  8. java web实现 忘记密码(找回密码)功能及代码

    java web实现 忘记密码(找回密码)功能及代码 (一).总体思路 (二).部分截图 (三).部分代码 (一).总体思路: 1.在 找回密码页面 录入 姓名.邮箱和验证码,录入后点击[提交]按钮, ...

  9. java Web工程师面试题集绵

    一.Java 基础 1.JDK .JRE 和JVM关系是什么? 答:A. JDK(Java Development Kit)即Java开发工具包,包含编写Java程序所必须的编译.运行等开发工具以及J ...

  10. @Java web程序员,在保留现场,服务不重启的情况下,执行我们的调试代码(JSP 方式)

    一.前言 类加载器实战系列的第六篇(悄悄跟你说,这篇比较水),前面5篇在这里: 实战分析Tomcat的类加载器结构(使用Eclipse MAT验证) 还是Tomcat,关于类加载器的趣味实验 了不得, ...

随机推荐

  1. Qt音视频开发31-Onvif抓拍图片

    一.前言 抓拍是个很重要的功能,比如在报警视频联动中需要一张实时的图片,很多SDK不提供抓拍功能,而通过预览抓图,得到的图片已不具有实时性,那如何得到实时的图片呢?现在的IPC基本上都支持ONVIF协 ...

  2. FFmpeg中的色彩空间与像素格式2-RGB/YUV色彩空间

    cnblogs 网站将文本J:a:b渲染成了J️b.是否可通过设置博客后台解决此问题?有知道的同学请留言指点一下,谢谢. FFmpeg 中的色彩与像素系列文章如下: [1]. FFmpeg中的色彩空间 ...

  3. 禁用Windows服务器iis错误导致启动vs调试

    问题描述: IIS站点错误会导致windows服务器启动vs调试,这在生产服务器是完全没必要的,会导致下面的问题,弹出一个调试框,必须手动关闭.很是不爽.. 关闭调试导入注册表: Windows Re ...

  4. Solution -「CF 1366E2」Chiori and Doll Picking (hard version)

    \(\mathscr{Description}\)   Link.   给定 \(\{a_n\}\), 值域 \([0,2^m)\). 对于每个 \(i\in[0,m]\), 求有多少个 \(\{a_ ...

  5. 1011. 在 D 天内送达包裹的能力

    在 D 天内送达包裹的能力 传送带上的包裹必须在 days 天内从一个港口运送到另一个港口. 传送带上的第 i 个包裹的重量为 weights[i].每一天,我们都会按给出重量(weights)的顺序 ...

  6. win10 bat文件命令大全-快捷键

    具体介绍: 1. echo 和 @回显命令 @                     #关闭单行回显 echo off              #从下一行开始关闭回显 @echo off      ...

  7. Python使用技巧2

    python url网址拼接 在做爬虫中,经常会遇到需要把一个域名和网址路径进行拼接,在开发时一时没想到方法,特此记录下来. 利用parse.urljoin方法进行网址拼接 from urllib i ...

  8. 构建强大算力基础,奠定AI时代基石!

    7月6日,2023世界人工智能大会在上海拉开序幕.由中国电信主办的"算网一体 融创未来"主题论坛也于当日在上海世博中心举行.上海市经济和信息化委员会副主任戎之勤.上海市金山区人民政 ...

  9. [业界方案] Yarn的业界解决方案和未来方向

    [业界方案] Yarn的业界解决方案和未来方向 目录 [业界方案] Yarn的业界解决方案和未来方向 0x00 摘要 0x01 Yarn 1.1 参考文章 0x02 分析 2.1 综述 2.1.1 y ...

  10. nginx 简单实践:正向代理、反向代理【nginx 实践系列之二】

    〇.前言 本文为 nginx 简单实践系列文章之二,主要简单实践了两个内容:正向代理.反向代理,仅供参考. 关于 Nginx 基础,以及安装和配置详解,可以参考博主过往文章: https://www. ...