• java处理苹果浏览器safari无法播放视频流(Accept-Ranges)


    https://blog.csdn.net/u010120886/article/details/79007001

    最近在做一个在线播放视频流的程序,安卓和电脑上都可以正常的播放。可以唯独ios上无法正常播放。开始在网上找了很多资料觉得不是很到位,所以在这里记录一下。

    刚开始时代码返回的视频流是在一个请求里全部返回的,而苹果的浏览器会先发一次探测请求来获取文件大小,之后再发送多次请求来分段取数据流的数据,其实这里就是一个分段上传的思想(Accept-Ranges)。有两个很重要的点就是,

    第一:需要根据请求内容的不同做出不同的响应,第一次探测请求需要返回200,后面的请求需要返回206和具体数据

    第二:contentType必须设置为video/mp4。

    下面是可以直接使用的代码:

    private void sendVideo(HttpServletRequest request, HttpServletResponse response, File file, String fileName) throws FileNotFoundException, IOException {
            RandomAccessFile randomFile = new RandomAccessFile(file, "r");//只读模式
            long contentLength = randomFile.length();
            String range = request.getHeader("Range");
            int start = 0, end = 0;
            if(range != null && range.startsWith("bytes=")){
                String[] values = range.split("=")[1].split("-");
                start = Integer.parseInt(values[0]);
                if(values.length > 1){
                    end = Integer.parseInt(values[1]);
                }
            }
            int requestSize = 0;
            if(end != 0 && end > start){
                requestSize = end - start + 1;
            } else {
                requestSize = Integer.MAX_VALUE;
            }
     
            byte[] buffer = new byte[4096];
            response.setContentType("video/mp4");
            response.setHeader("Accept-Ranges", "bytes");
            response.setHeader("ETag", fileName);
            response.setHeader("Last-Modified", new Date().toString());
            //第一次请求只返回content length来让客户端请求多次实际数据
            if(range == null){
                response.setHeader("Content-length", contentLength + "");
            }else{
                //以后的多次以断点续传的方式来返回视频数据
                response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);//206
                long requestStart = 0, requestEnd = 0;
                String[] ranges = range.split("=");
                if(ranges.length > 1){
                    String[] rangeDatas = ranges[1].split("-");
                    requestStart = Integer.parseInt(rangeDatas[0]);
                    if(rangeDatas.length > 1){
                        requestEnd = Integer.parseInt(rangeDatas[1]);
                    }
                }
                long length = 0;
                if(requestEnd > 0){
                    length = requestEnd - requestStart + 1;
                    response.setHeader("Content-length", "" + length);
                    response.setHeader("Content-Range", "bytes " + requestStart + "-" + requestEnd + "/" + contentLength);
                }else{
                    length = contentLength - requestStart;
                    response.setHeader("Content-length", "" + length);
                    response.setHeader("Content-Range", "bytes "+ requestStart + "-" + (contentLength - 1) + "/" + contentLength);
                }
            }
            ServletOutputStream out = response.getOutputStream();
            int needSize = requestSize;
            randomFile.seek(start);
            while(needSize > 0){
                int len = randomFile.read(buffer);
                if(needSize < buffer.length){
                    out.write(buffer, 0, needSize);
                } else {
                    out.write(buffer, 0, len);
                    if(len < buffer.length){
                        break;
                    }
                }
                needSize -= buffer.length;
            }
            randomFile.close();
            out.close();
            
        }
  • 相关阅读:
    springmvc视频学习
    两个数组a和b,都已经升序排列. 查找相同的元素?(要求不使用两层for循环)
    https Java SSL Exception protocol_version
    java多线程笔试题:设计4个线程,其中两个线程每次对j增加1,另外2个线程每次对j减少1.写出程序
    java多线程笔试题:子线程循环10次;接着主线程循环20次,接着又子线程循环10次,接着再回到主线程又循环20次,如此循环50次,请写出程序。
    R语言学习笔记
    重建二叉树-牛客网-剑指offer
    字符串替换空格-牛客网-剑指offer
    二维数组中的查找-牛客网-剑指offer
    牛客网-剑指offer-java版本解答目录(经自测)
  • 原文地址:https://www.cnblogs.com/kelelipeng/p/14151102.html
Copyright © 2020-2023  润新知