Chrome浏览器Video无法拖动的探索和解决方案

适用于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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值