java web 传输视频流代码锦集
方案一
//path为本地文件路劲 public void play(String path, HttpServletRequest request, HttpServletResponse response) { RandomAccessFile targetFile = null; OutputStream outputStream = null; try { outputStream = response.getOutputStream(); response.reset(); //获取请求头中Range的值 String rangeString = request.getHeader(HttpHeaders.RANGE); //打开文件 File file = new File(path); if (file.exists()) { //使用RandomAccessFile读取文件 targetFile = new RandomAccessFile(file, "r"); long fileLength = targetFile.length(); long requestSize = (int) fileLength; //分段下载视频 if (StringUtils.hasText(rangeString)) { //从Range中提取需要获取数据的开始和结束位置 long requestStart = 0, requestEnd = 0; String[] ranges = rangeString.split("="); if (ranges.length > 1) { String[] rangeDatas = ranges[1].split("-"); requestStart = Integer.parseInt(rangeDatas[0]); if (rangeDatas.length > 1) { requestEnd = Integer.parseInt(rangeDatas[1]); } } if (requestEnd != 0 && requestEnd > requestStart) { requestSize = requestEnd - requestStart + 1; } //根据协议设置请求头 response.setHeader(HttpHeaders.ACCEPT_RANGES, "bytes"); response.setHeader(HttpHeaders.CONTENT_TYPE, "video/mp4"); if (!StringUtils.hasText(rangeString)) { response.setHeader(HttpHeaders.CONTENT_LENGTH, fileLength + ""); } else { long length; if (requestEnd > 0) { length = requestEnd - requestStart + 1; response.setHeader(HttpHeaders.CONTENT_LENGTH, "" + length); response.setHeader(HttpHeaders.CONTENT_RANGE, "bytes " + requestStart + "-" + requestEnd + "/" + fileLength); } else { length = fileLength - requestStart; response.setHeader(HttpHeaders.CONTENT_LENGTH, "" + length); response.setHeader(HttpHeaders.CONTENT_RANGE, "bytes " + requestStart + "-" + (fileLength - 1) + "/" + fileLength); } } //断点传输下载视频返回206 response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT); //设置targetFile,从自定义位置开始读取数据 targetFile.seek(requestStart); } else { //如果Range为空则下载整个视频 response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=test.mp4"); //设置文件长度 response.setHeader(HttpHeaders.CONTENT_LENGTH, String.valueOf(fileLength)); } //从磁盘读取数据流返回 byte[] cache = new byte[4096]; try { while (requestSize > 0) { int len = targetFile.read(cache); if (requestSize < cache.length) { outputStream.write(cache, 0, (int) requestSize); } else { outputStream.write(cache, 0, len); if (len < cache.length) { break; } } requestSize -= cache.length; } } catch (IOException e) { // tomcat原话。写操作IO异常几乎总是由于客户端主动关闭连接导致,所以直接吃掉异常打日志 //比如使用video播放视频时经常会发送Range为0- 的范围只是为了获取视频大小,之后就中断连接了 log.info(e.getMessage()); } } else { throw new RuntimeException("文件路劲有误"); } outputStream.flush(); } catch (Exception e) { log.error("文件传输错误", e); throw new RuntimeException("文件传输错误"); }finally { if(outputStream != null){ try { outputStream.close(); } catch (IOException e) { log.error("流释放错误", e); } } if(targetFile != null){ try { targetFile.close(); } catch (IOException e) { log.error("文件流释放错误", e); } } } }
方案二
/** * 获取视频流 * @param response * @param fileName 视频存放信息索引 * @return */ @RequestMapping("/getVideo") public void getVideo(HttpServletRequest request, HttpServletResponse response,String fileName) { //视频资源存储信息 response.reset(); //获取从那个字节开始读取文件 String rangeString = request.getHeader("Range"); log.info("getVideo获取视频资源:{},读取文件字节:{}",fileName,rangeString); try { //获取响应的输出流 OutputStream outputStream = response.getOutputStream(); File file = new File(fileName); if(file.exists()){ RandomAccessFile targetFile = new RandomAccessFile(file, "r"); long fileLength = targetFile.length(); //播放 if(rangeString != null){ long range = Long.parseLong(rangeString.substring(rangeString.indexOf("=") + 1, rangeString.indexOf("-"))); //设置内容类型 response.setHeader("Content-Type", "video/mov"); //设置此次相应返回的数据长度 response.setHeader("Content-Length", String.valueOf(fileLength - range)); //设置此次相应返回的数据范围 response.setHeader("Content-Range", "bytes "+range+"-"+(fileLength-1)+"/"+fileLength); //返回码需要为206,而不是200 response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT); //设定文件读取开始位置(以字节为单位) targetFile.seek(range); }else {//下载 //设置响应头,把文件名字设置好 response.setHeader("Content-Disposition", "attachment; filename="+fileName ); //设置文件长度 response.setHeader("Content-Length", String.valueOf(fileLength)); //解决编码问题 response.setHeader("Content-Type","application/octet-stream"); } byte[] cache = new byte[1024 * 300]; int flag; while ((flag = targetFile.read(cache))!=-1){ outputStream.write(cache, 0, flag); } }else { String message = "file:"+fileName+" not exists"; //解决编码问题 response.setHeader("Content-Type","application/json"); outputStream.write(message.getBytes(StandardCharsets.UTF_8)); } outputStream.flush(); outputStream.close(); } catch (FileNotFoundException e) { } catch (IOException e) { } }