[Spring Boot]Safari(iPhone系浏览器)相关无法播放视频

近期在存储服务。遇到了一个棘手的问题,电脑端,包括了Android的浏览器,应用都能正常的播放上传的mp4应用,但是链接一到苹果上就有问题了。

搜了网上很快发现了问题。是因为苹果的要求很奇葩。

苹果会发两次请求,第一次请求是不带Range的,这一波是只能返回Content-Length的,不能返回Content-Range以及其他的。

第二波是需要根据苹果的请求的Range来返回Range的内的数据,然后状态码要设置为206,才不会出问题。

另外。在ContentType上也有问题,就是如果你的mp4的Content-Type设置为video/mpeg4 也是不行的,也只能是video/mp4才可以访问。

重点已经讲完,下面是研究完成粗写的代码。部分方法你们是没有的,请不要照抄,请根据修改。

 

   public void readAndFlush(String fileContentType,File file,HttpServletResponse response,String fileId,boolean needCache,String fileName,String range) throws UploadException{
        int statusCode = 200;
        try {
            response.addHeader("Content-Type",fileContentType);
            response.addHeader("Cache-Control","max-age=259200");
            String fileType = FileUtils.getFileType(fileName);
            if (fileType.equals(FileConstant.TYPE_VEDIO)){
                response.setHeader("content-disposition", "inline");
            }else if (fileType.equals(FileConstant.TYPE_IMAGE)){
                response.setHeader("content-disposition", "inline");
            }else {
                response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
            }
            InputStream inputStream = new FileInputStream(file);
            //开始处理ContentRange
            long startByte = 0;
            long endByte = (inputStream.available() - 1);
            long contentLength = endByte - startByte + 1;
            if (range != null && range.contains("bytes") && range.contains("-")){
                statusCode = 206;
                range = range.substring(range.lastIndexOf("=") + 1).trim();
                String ranges[] = range.split("-");
                try {
                    //根据range解析下载分片的位置区间
                    if (ranges.length == 1) {
                        //情况1,如:bytes=-1024  从开始字节到第1024个字节的数据
                        if (range.startsWith("-")) {
                            endByte = Long.parseLong(ranges[0]);
                        }
                        //情况2,如:bytes=1024-  第1024个字节到最后字节的数据
                        else if (range.endsWith("-")) {
                            startByte = Long.parseLong(ranges[0]);
                        }
                    }
                    //情况3,如:bytes=1024-2048  第1024个字节到2048个字节的数据
                    else if (ranges.length == 2) {
                        startByte = Long.parseLong(ranges[0]);
                        endByte = Long.parseLong(ranges[1]);
                    }


                } catch (NumberFormatException e) {
                    startByte = 0;
                    endByte = (inputStream.available() - 1);
                }
                contentLength = endByte - startByte + 1;
                response.setHeader("Content-Length",String.valueOf(contentLength));
            }
            // 处理请求的Range完成,开始进行字节流操作。

            BufferedOutputStream outputStream = new BufferedOutputStream(response.getOutputStream());
            long startRange = startByte;
            long endRange = endByte;
            if (range == null){
                startRange = 0;
                endRange = 1;
            }

            response.setHeader("Content-Range","bytes "+startRange+"-"+endRange+"/"+String.valueOf(inputStream.available()));

            // 开始进行传输大小的操作
            long transmitted = 0;
            byte[] buff = new byte[2048];
            int len = 0;
            while ((transmitted + len) <= contentLength && (len = inputStream.read(buff)) != -1) {
                outputStream.write(buff, 0, len);
                transmitted += len;
            }
            //处理不足buff.length部分
            if (transmitted < contentLength) {
                len = inputStream.read(buff, 0, (int) (contentLength - transmitted));
                outputStream.write(buff, 0, len);
                transmitted += len;
            }

//            IOUtils.copy(inputStream,response.getOutputStream());
            response.setStatus(statusCode);
            outputStream.flush();
            response.flushBuffer();
            if (needCache){
                cacheService.cacheToRedis(fileId);
            }
        }catch (Exception e){
            logger.info("读取数据并返回时失败,文件id为:"+fileId+",文件类型为:"+fileContentType,e);
            e.printStackTrace();
            throw new UploadException("读取数据并返回失败");
        }
    }

未经允许不得转载:RffanLAB|Rffan实验室 » [Spring Boot]Safari(iPhone系浏览器)相关无法播放视频

赞 (4) 打赏

评论 0

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏