近期在存储服务。遇到了一个棘手的问题,电脑端,包括了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系浏览器)相关无法播放视频