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

最近在做一个在线播放视频流的程序,安卓和电脑上都可以正常的播放。可以唯独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();

}


作者:通信二师

来源:CSDN

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

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容