Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to use data stream to play video in Html5

2025-01-17 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/01 Report--

这篇文章主要为大家展示了"怎么在Html5使用数据流播放视频",内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下"怎么在Html5使用数据流播放视频"这篇文章吧。

H5页面可以通过 标签来播放视频。一般的方式如下:

your browser does not support the video tag

src中指定了要播放的视频的URL,为具体的视频文件路径。当将访问请求变为getVideo.do?fileId=xxx 这种形式,服务端返回字节流的时候后端实现需要一些更改。

一般的方式是读本地文件然后写到response中,代码实现如下:

public void downFile(File downloadFile, HttpServletResponse response, HttpServletRequest request) throws Exception { response.reset(); response.setContentType("video/mp4;charset=UTF-8"); InputStream in = null; ServletOutputStream out = null; try { out = response.getOutputStream(); in = new FileInputStream(downloadFile); if(in !=null){ byte[] b = new byte[1024]; int i = 0; while((i = in.read(b)) > 0){ out.write(b, 0, i); } out.flush(); in.close(); } } catch (Exception e) { e.printStackTrace(); }finally{ if(in != null) { try { in.close(); } catch (IOException e) { } in = null; } if(out != null) { try { out.close(); } catch (IOException e) { } out = null; } }}

这种方式在PC端和Android手机上都能正常显示,但在IOS手机上通过Safari浏览器就不能播放。ios目前获取视频的时候请求头会带一个与断点续传有关的信息。对于ios来说,他不是一次性请求全部文件的,一般首先会请求0-1字节,这个会写在request header的"range"字段中:range:'bytes=0-1'。而服务端必须满足range的要求:解析range字段,然后按照range字段的要求返回对应的数据。

在响应头中response header至少要包含三个字段:

Content-Type:明确指定视频格式,有"video/mp4", "video/ogg", "video/mov"等等。

Content-Range:格式是 "bytes -/",其中start和end必需对应request header里的range字段,total是文件总大小。

Content-Length:返回的二进制长度。

断点续传实现如下:

public void downRangeFile(File downloadFile, HttpServletResponse response, HttpServletRequest request) throws Exception { if (!downloadFile.exists()) { response.sendError(HttpServletResponse.SC_NOT_FOUND); return; } long fileLength = downloadFile.length();// 记录文件大小 long pastLength = 0;// 记录已下载文件大小 int rangeSwitch = 0;// 0:从头开始的全文下载;1:从某字节开始的下载(bytes=27000-);2:从某字节开始到某字节结束的下载(bytes=27000-39000) long contentLength = 0;// 客户端请求的字节总量 String rangeBytes = "";// 记录客户端传来的形如"bytes=27000-"或者"bytes=27000-39000"的内容 RandomAccessFile raf = null;// 负责读取数据 OutputStream os = null;// 写出数据 OutputStream out = null;// 缓冲 int bsize = 1024;// 缓冲区大小 byte b[] = new byte[bsize];// 暂存容器 String range = request.getHeader("Range"); int responseStatus = 206; if (range != null && range.trim().length() > 0 && !"null".equals(range)) {// 客户端请求的下载的文件块的开始字节 responseStatus = javax.servlet.http.HttpServletResponse.SC_PARTIAL_CONTENT; System.out.println("request.getHeader("Range")=" + range); rangeBytes = range.replaceAll("bytes=", ""); if (rangeBytes.endsWith("-")) { rangeSwitch = 1; rangeBytes = rangeBytes.substring(0, rangeBytes.indexOf('-')); pastLength = Long.parseLong(rangeBytes.trim()); contentLength = fileLength - pastLength; } else { rangeSwitch = 2; String temp0 = rangeBytes.substring(0, rangeBytes.indexOf('-')); String temp2 = rangeBytes.substring(rangeBytes.indexOf('-') + 1, rangeBytes.length()); pastLength = Long.parseLong(temp0.trim()); } } else { contentLength = fileLength;// 客户端要求全文下载 } // 清除首部的空白行 response.reset(); // 告诉客户端允许断点续传多线程连接下载,响应的格式是:Accept-Ranges: bytes response.setHeader("Accept-Ranges", "bytes"); // 如果是第一次下,还没有断点续传,状态是默认的 200,无需显式设置;响应的格式是:HTTP/1.1 if (rangeSwitch != 0) { response.setStatus(responseStatus); // 不是从最开始下载,断点下载响应号为206 // 响应的格式是: // Content-Range: bytes [文件块的开始字节]-[文件的总大小 - 1]/[文件的总大小] switch (rangeSwitch) { case 1: { String contentRange = new StringBuffer("bytes ") .append(new Long(pastLength).toString()).append("-") .append(new Long(fileLength - 1).toString()) .append("/").append(new Long(fileLength).toString()) .toString(); response.setHeader("Content-Range", contentRange); break; } case 2: { String contentRange = range.replace("=", " ") + "/" + new Long(fileLength).toString(); response.setHeader("Content-Range", contentRange); break; } default: { break; } } } else { String contentRange = new StringBuffer("bytes ").append("0-") .append(fileLength - 1).append("/").append(fileLength) .toString(); response.setHeader("Content-Range", contentRange); } try { response.setContentType("video/mp4;charset=UTF-8"); response.setHeader("Content-Length", String.valueOf(contentLength)); os = response.getOutputStream(); out = new BufferedOutputStream(os); raf = new RandomAccessFile(downloadFile, "r"); try { long outLength = 0;// 实际输出字节数 switch (rangeSwitch) { case 0: { } case 1: { raf.seek(pastLength); int n = 0; while ((n = raf.read(b)) != -1) { out.write(b, 0, n); outLength += n; } break; } case 2: { raf.seek(pastLength); int n = 0; long readLength = 0;// 记录已读字节数 while (readLength

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report