适用于MP4无法通过URL作为静态内容返回的场景。
环境:
1:spring boot
2:客户端 Chrome 浏览器
3:播放环境 Video原生标签
4:MP4物理路径无法无法直接请求到数据,需通过程序读取到内存然后返回。(如果这个MP4是静态内容,不需要程序处理,则一般不会有这个问题)
问题:
无法进行拖放或者拖放以后要重头进行播放。
故障原因:
与Video标签适配的请求未被响应。
如何做:
1:Chrome浏览器默认请求会在 Header 添加一个Range如下:服务器要做的就是响应这个Header
Range: bytes=0-
2:服务器接收到这个Header以后,响应的Header如下,同时需要设置状态码为206
Accept-Ranges: bytes
Content-Length: 2097152
Content-Range: bytes 0-2097151/38696534
3:服务端代码实现
/**
* 处理资源响应数据和响应头
* @param request
* @param response
* @param data
* @return
*/
private byte[] handleResponseDataAndHeader(HttpServletRequest request, HttpServletResponse response, byte[] data) {
String url = request.getRequestURL().toString();
String contentType = ContentTypeUtil.typeOfUrl(url);
if (!StringUtils.isEmpty(contentType)) {
response.setContentType(contentType);
}
response.setContentLength(data.length);
// 缓存一天
response.setHeader("Cache-Control", "max-age=86400000");
String rangeString = request.getHeader("Range");
if (StringUtils.isEmpty(rangeString)) {
return data;
}
return handleExistRangeResponseDataAndHeader(request, response, data);
}
/**
* 处理请求头带range的资源响应数据和响应头
* @param request
* @param response
* @param data
* @return
*/
private byte[] handleExistRangeResponseDataAndHeader(HttpServletRequest request,
HttpServletResponse response, byte[] data) {
// 一次返回2M数据
int onceDataLength = 2 * 1024 * 1024;
String rangeString = request.getHeader("Range");
int[] rangeArray = getRangeArrayFromRangeString(rangeString, onceDataLength);
if (rangeArray[1] > data.length-1) {
rangeArray[1] = data.length-1;
}
response.setHeader("Content-Range",
"bytes " + rangeArray[0] + "-" + rangeArray[1] + "/" + data.length);
response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
response.addHeader("Accept-Ranges", "bytes");
int byteLength = rangeArray[1] - rangeArray[0] + 1;
response.setContentLength(byteLength);
byte[] onceData = new byte[byteLength];
System.arraycopy(data, rangeArray[0], onceData, 0, byteLength);
return onceData;
}
/**
* 获取请求需要的数据范围
* @param rangeString
* @param dataLength
* @return
*/
private int[] getRangeArrayFromRangeString(String rangeString, int dataLength) {
int[] rangeArray = new int[2];
rangeString = rangeString.substring(rangeString.indexOf("=") + 1);
String rangeStartString = rangeString.substring(0, rangeString.indexOf("-"));
if (StringUtils.hasText(rangeStartString.trim())) {
rangeArray[0] = Integer.parseInt(rangeStartString.trim());
} else {
rangeArray[0] = 0;
}
if (rangeString.indexOf("-") == rangeString.length()-1) {
rangeArray[1] = rangeArray[0] + dataLength - 1;
} else {
String rangeEndString = rangeString.substring(rangeString.indexOf("-") + 1);
if (StringUtils.hasText(rangeEndString.trim())) {
rangeArray[1] = Integer.parseInt(rangeEndString.trim());
} else {
rangeArray[1] = rangeArray[0] + dataLength - 1;
}
}
return rangeArray;
}
参考原文链接:
https://blog.csdn.net/hudaijun/article/details/87456583